1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.mtp; 18 19import android.content.Context; 20import android.mtp.MtpObjectInfo; 21import android.os.ParcelFileDescriptor; 22import android.util.SparseArray; 23 24import java.io.IOException; 25import java.util.ArrayList; 26import java.util.Arrays; 27import java.util.HashMap; 28import java.util.Map; 29 30public class TestMtpManager extends MtpManager { 31 public static final int CREATED_DOCUMENT_HANDLE = 1000; 32 33 protected static String pack(int... args) { 34 return Arrays.toString(args); 35 } 36 37 private final SparseArray<MtpDeviceRecord> mDevices = new SparseArray<>(); 38 private final Map<String, MtpObjectInfo> mObjectInfos = new HashMap<>(); 39 private final Map<String, int[]> mObjectHandles = new HashMap<>(); 40 private final Map<String, byte[]> mThumbnailBytes = new HashMap<>(); 41 private final Map<String, byte[]> mImportFileBytes = new HashMap<>(); 42 private final Map<String, Long> mObjectSizeLongs = new HashMap<>(); 43 44 TestMtpManager(Context context) { 45 super(context); 46 } 47 48 void addValidDevice(MtpDeviceRecord device) { 49 mDevices.put(device.deviceId, device); 50 } 51 52 void setObjectHandles(int deviceId, int storageId, int parentHandle, int[] objectHandles) { 53 mObjectHandles.put(pack(deviceId, storageId, parentHandle), objectHandles); 54 } 55 56 void setObjectInfo(int deviceId, MtpObjectInfo objectInfo) { 57 mObjectInfos.put(pack(deviceId, objectInfo.getObjectHandle()), objectInfo); 58 } 59 60 void setImportFileBytes(int deviceId, int objectHandle, byte[] bytes) { 61 mImportFileBytes.put(pack(deviceId, objectHandle), bytes); 62 } 63 64 byte[] getImportFileBytes(int deviceId, int objectHandle) { 65 return mImportFileBytes.get(pack(deviceId, objectHandle)); 66 } 67 68 void setThumbnail(int deviceId, int objectHandle, byte[] bytes) { 69 mThumbnailBytes.put(pack(deviceId, objectHandle), bytes); 70 } 71 72 void setObjectSizeLong(int deviceId, int objectHandle, int format, long value) { 73 mObjectSizeLongs.put(pack(deviceId, objectHandle, format), value); 74 } 75 76 @Override 77 MtpDeviceRecord[] getDevices() { 78 final MtpDeviceRecord[] result = new MtpDeviceRecord[mDevices.size()]; 79 for (int i = 0; i < mDevices.size(); i++) { 80 final MtpDeviceRecord device = mDevices.valueAt(i); 81 if (device.opened) { 82 result[i] = device; 83 } else { 84 result[i] = new MtpDeviceRecord( 85 device.deviceId, device.name, device.deviceKey, device.opened, 86 new MtpRoot[0], null, null); 87 } 88 } 89 return result; 90 } 91 92 @Override 93 MtpDeviceRecord openDevice(int deviceId) throws IOException { 94 final MtpDeviceRecord device = mDevices.get(deviceId); 95 if (device == null) { 96 throw new IOException(); 97 } 98 final MtpDeviceRecord record = new MtpDeviceRecord( 99 device.deviceId, device.name, device.deviceKey, true, device.roots, 100 device.operationsSupported, device.eventsSupported); 101 mDevices.put(deviceId, record); 102 return record; 103 } 104 105 @Override 106 void closeDevice(int deviceId) throws IOException { 107 final MtpDeviceRecord device = mDevices.get(deviceId); 108 if (device == null) { 109 throw new IOException(); 110 } 111 mDevices.put( 112 deviceId, 113 new MtpDeviceRecord(device.deviceId, device.name, device.deviceKey, false, 114 device.roots, device.operationsSupported, device.eventsSupported)); 115 } 116 117 @Override 118 MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException { 119 final String key = pack(deviceId, objectHandle); 120 if (mObjectInfos.containsKey(key)) { 121 return mObjectInfos.get(key); 122 } else { 123 throw new IOException("getObjectInfo error: " + key); 124 } 125 } 126 127 @Override 128 int[] getObjectHandles(int deviceId, int storageId, int parentObjectHandle) throws IOException { 129 final String key = pack(deviceId, storageId, parentObjectHandle); 130 if (mObjectHandles.containsKey(key)) { 131 return mObjectHandles.get(key); 132 } else { 133 throw new IOException("getObjectHandles error: " + key); 134 } 135 } 136 137 @Override 138 void importFile(int deviceId, int objectHandle, ParcelFileDescriptor target) 139 throws IOException { 140 final String key = pack(deviceId, objectHandle); 141 if (mImportFileBytes.containsKey(key)) { 142 try (final ParcelFileDescriptor.AutoCloseOutputStream outputStream = 143 new ParcelFileDescriptor.AutoCloseOutputStream(target)) { 144 outputStream.write(mImportFileBytes.get(key)); 145 } 146 } else { 147 throw new IOException("importFile error: " + key); 148 } 149 } 150 151 @Override 152 int createDocument(int deviceId, MtpObjectInfo objectInfo, ParcelFileDescriptor source) 153 throws IOException { 154 final String key = pack(deviceId, CREATED_DOCUMENT_HANDLE); 155 if (mObjectInfos.containsKey(key)) { 156 throw new IOException(); 157 } 158 final MtpObjectInfo newInfo = new MtpObjectInfo.Builder(objectInfo). 159 setObjectHandle(CREATED_DOCUMENT_HANDLE).build(); 160 mObjectInfos.put(key, newInfo); 161 if (objectInfo.getFormat() != 0x3001) { 162 try (final ParcelFileDescriptor.AutoCloseInputStream inputStream = 163 new ParcelFileDescriptor.AutoCloseInputStream(source)) { 164 final byte[] buffer = new byte[objectInfo.getCompressedSize()]; 165 if (inputStream.read(buffer, 0, objectInfo.getCompressedSize()) != 166 objectInfo.getCompressedSize()) { 167 throw new IOException(); 168 } 169 170 mImportFileBytes.put(pack(deviceId, CREATED_DOCUMENT_HANDLE), buffer); 171 } 172 } 173 return CREATED_DOCUMENT_HANDLE; 174 } 175 176 @Override 177 byte[] getThumbnail(int deviceId, int objectHandle) throws IOException { 178 final String key = pack(deviceId, objectHandle); 179 if (mThumbnailBytes.containsKey(key)) { 180 return mThumbnailBytes.get(key); 181 } else { 182 throw new IOException("getThumbnail error: " + key); 183 } 184 } 185 186 @Override 187 void deleteDocument(int deviceId, int objectHandle) throws IOException { 188 final String key = pack(deviceId, objectHandle); 189 if (mObjectInfos.containsKey(key)) { 190 mObjectInfos.remove(key); 191 } else { 192 throw new IOException(); 193 } 194 } 195 196 @Override 197 int getParent(int deviceId, int objectHandle) throws IOException { 198 final String key = pack(deviceId, objectHandle); 199 if (mObjectInfos.containsKey(key)) { 200 return mObjectInfos.get(key).getParent(); 201 } else { 202 throw new IOException(); 203 } 204 } 205 206 @Override 207 byte[] getObject(int deviceId, int objectHandle, int expectedSize) throws IOException { 208 return mImportFileBytes.get(pack(deviceId, objectHandle)); 209 } 210 211 @Override 212 long getPartialObject(int deviceId, int objectHandle, long offset, long size, byte[] buffer) 213 throws IOException { 214 final byte[] bytes = mImportFileBytes.get(pack(deviceId, objectHandle)); 215 int i = 0; 216 while (i < size && i + offset < bytes.length) { 217 buffer[i] = bytes[(int) (i + offset)]; 218 i++; 219 } 220 return i; 221 } 222 223 @Override 224 long getObjectSizeLong(int deviceId, int objectHandle, int format) throws IOException { 225 final String key = pack(deviceId, objectHandle, format); 226 if (mObjectSizeLongs.containsKey(key)) { 227 return mObjectSizeLongs.get(key); 228 } else { 229 throw new IOException(); 230 } 231 } 232} 233