1 /* 2 * Copyright (C) 2010 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 17 package com.android.gallery3d.data; 18 19 import android.annotation.TargetApi; 20 import android.hardware.usb.UsbDevice; 21 import android.mtp.MtpConstants; 22 import android.mtp.MtpObjectInfo; 23 import android.mtp.MtpStorageInfo; 24 import android.net.Uri; 25 import android.util.Log; 26 27 import com.android.gallery3d.app.GalleryApp; 28 import com.android.gallery3d.common.ApiHelper; 29 30 import java.util.ArrayList; 31 import java.util.List; 32 33 @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB_MR1) 34 public class MtpDevice extends MediaSet { 35 private static final String TAG = "MtpDevice"; 36 37 private final GalleryApp mApplication; 38 private final int mDeviceId; 39 private final String mDeviceName; 40 private final MtpContext mMtpContext; 41 private final String mName; 42 private final ChangeNotifier mNotifier; 43 private final Path mItemPath; 44 private List<MtpObjectInfo> mJpegChildren; 45 46 public MtpDevice(Path path, GalleryApp application, int deviceId, 47 String name, MtpContext mtpContext) { 48 super(path, nextVersionNumber()); 49 mApplication = application; 50 mDeviceId = deviceId; 51 mDeviceName = UsbDevice.getDeviceName(deviceId); 52 mMtpContext = mtpContext; 53 mName = name; 54 mNotifier = new ChangeNotifier(this, Uri.parse("mtp://"), application); 55 mItemPath = Path.fromString("/mtp/item/" + String.valueOf(deviceId)); 56 mJpegChildren = new ArrayList<MtpObjectInfo>(); 57 } 58 59 public MtpDevice(Path path, GalleryApp application, int deviceId, 60 MtpContext mtpContext) { 61 this(path, application, deviceId, 62 MtpDeviceSet.getDeviceName(mtpContext, deviceId), mtpContext); 63 } 64 65 private List<MtpObjectInfo> loadItems() { 66 ArrayList<MtpObjectInfo> result = new ArrayList<MtpObjectInfo>(); 67 68 List<MtpStorageInfo> storageList = mMtpContext.getMtpClient() 69 .getStorageList(mDeviceName); 70 if (storageList == null) return result; 71 72 for (MtpStorageInfo info : storageList) { 73 collectJpegChildren(info.getStorageId(), 0, result); 74 } 75 76 return result; 77 } 78 79 private void collectJpegChildren(int storageId, int objectId, 80 ArrayList<MtpObjectInfo> result) { 81 ArrayList<MtpObjectInfo> dirChildren = new ArrayList<MtpObjectInfo>(); 82 83 queryChildren(storageId, objectId, result, dirChildren); 84 85 for (int i = 0, n = dirChildren.size(); i < n; i++) { 86 MtpObjectInfo info = dirChildren.get(i); 87 collectJpegChildren(storageId, info.getObjectHandle(), result); 88 } 89 } 90 91 private void queryChildren(int storageId, int objectId, 92 ArrayList<MtpObjectInfo> jpeg, ArrayList<MtpObjectInfo> dir) { 93 List<MtpObjectInfo> children = mMtpContext.getMtpClient().getObjectList( 94 mDeviceName, storageId, objectId); 95 if (children == null) return; 96 97 for (MtpObjectInfo obj : children) { 98 int format = obj.getFormat(); 99 switch (format) { 100 case MtpConstants.FORMAT_JFIF: 101 case MtpConstants.FORMAT_EXIF_JPEG: 102 jpeg.add(obj); 103 break; 104 case MtpConstants.FORMAT_ASSOCIATION: 105 dir.add(obj); 106 break; 107 default: 108 Log.w(TAG, "other type: name = " + obj.getName() 109 + ", format = " + format); 110 } 111 } 112 } 113 114 public static MtpObjectInfo getObjectInfo(MtpContext mtpContext, int deviceId, 115 int objectId) { 116 String deviceName = UsbDevice.getDeviceName(deviceId); 117 return mtpContext.getMtpClient().getObjectInfo(deviceName, objectId); 118 } 119 120 @Override 121 public ArrayList<MediaItem> getMediaItem(int start, int count) { 122 ArrayList<MediaItem> result = new ArrayList<MediaItem>(); 123 int begin = start; 124 int end = Math.min(start + count, mJpegChildren.size()); 125 126 DataManager dataManager = mApplication.getDataManager(); 127 for (int i = begin; i < end; i++) { 128 MtpObjectInfo child = mJpegChildren.get(i); 129 Path childPath = mItemPath.getChild(child.getObjectHandle()); 130 synchronized (DataManager.LOCK) { 131 MtpImage image = (MtpImage) dataManager.peekMediaObject(childPath); 132 if (image == null) { 133 image = new MtpImage( 134 childPath, mApplication, mDeviceId, child, mMtpContext); 135 } else { 136 image.updateContent(child); 137 } 138 result.add(image); 139 } 140 } 141 return result; 142 } 143 144 @Override 145 public int getMediaItemCount() { 146 return mJpegChildren.size(); 147 } 148 149 @Override 150 public String getName() { 151 return mName; 152 } 153 154 @Override 155 public long reload() { 156 if (mNotifier.isDirty()) { 157 mDataVersion = nextVersionNumber(); 158 mJpegChildren = loadItems(); 159 } 160 return mDataVersion; 161 } 162 163 @Override 164 public int getSupportedOperations() { 165 return SUPPORT_IMPORT; 166 } 167 168 @Override 169 public boolean Import() { 170 return mMtpContext.copyAlbum(mDeviceName, mName, mJpegChildren); 171 } 172 173 @Override 174 public boolean isLeafAlbum() { 175 return true; 176 } 177 } 178