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.mtp.MtpDeviceInfo; 21 import android.net.Uri; 22 import android.os.Handler; 23 import android.util.Log; 24 25 import com.android.gallery3d.R; 26 import com.android.gallery3d.app.GalleryApp; 27 import com.android.gallery3d.common.ApiHelper; 28 import com.android.gallery3d.util.Future; 29 import com.android.gallery3d.util.FutureListener; 30 import com.android.gallery3d.util.MediaSetUtils; 31 import com.android.gallery3d.util.ThreadPool.Job; 32 import com.android.gallery3d.util.ThreadPool.JobContext; 33 34 import java.util.ArrayList; 35 import java.util.Collections; 36 import java.util.List; 37 38 // MtpDeviceSet -- MtpDevice -- MtpImage 39 @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB_MR1) 40 public class MtpDeviceSet extends MediaSet 41 implements FutureListener<ArrayList<MediaSet>> { 42 private static final String TAG = "MtpDeviceSet"; 43 44 private GalleryApp mApplication; 45 private final ChangeNotifier mNotifier; 46 private final MtpContext mMtpContext; 47 private final String mName; 48 private final Handler mHandler; 49 50 private Future<ArrayList<MediaSet>> mLoadTask; 51 private ArrayList<MediaSet> mDeviceSet = new ArrayList<MediaSet>(); 52 private ArrayList<MediaSet> mLoadBuffer; 53 private boolean mIsLoading; 54 MtpDeviceSet(Path path, GalleryApp application, MtpContext mtpContext)55 public MtpDeviceSet(Path path, GalleryApp application, MtpContext mtpContext) { 56 super(path, nextVersionNumber()); 57 mApplication = application; 58 mNotifier = new ChangeNotifier(this, Uri.parse("mtp://"), application); 59 mMtpContext = mtpContext; 60 mName = application.getResources().getString(R.string.set_label_mtp_devices); 61 mHandler = new Handler(mApplication.getMainLooper()); 62 } 63 64 private class DevicesLoader implements Job<ArrayList<MediaSet>> { 65 @Override run(JobContext jc)66 public ArrayList<MediaSet> run(JobContext jc) { 67 DataManager dataManager = mApplication.getDataManager(); 68 ArrayList<MediaSet> result = new ArrayList<MediaSet>(); 69 70 // Enumerate all devices 71 List<android.mtp.MtpDevice> devices = mMtpContext.getMtpClient().getDeviceList(); 72 Log.v(TAG, "loadDevices: " + devices + ", size=" + devices.size()); 73 for (android.mtp.MtpDevice mtpDevice : devices) { 74 synchronized (DataManager.LOCK) { 75 int deviceId = mtpDevice.getDeviceId(); 76 Path childPath = mPath.getChild(deviceId); 77 MtpDevice device = (MtpDevice) dataManager.peekMediaObject(childPath); 78 if (device == null) { 79 device = new MtpDevice(childPath, mApplication, deviceId, mMtpContext); 80 } 81 Log.d(TAG, "add device " + device); 82 result.add(device); 83 } 84 } 85 Collections.sort(result, MediaSetUtils.NAME_COMPARATOR); 86 return result; 87 } 88 } 89 getDeviceName(MtpContext mtpContext, int deviceId)90 public static String getDeviceName(MtpContext mtpContext, int deviceId) { 91 android.mtp.MtpDevice device = mtpContext.getMtpClient().getDevice(deviceId); 92 if (device == null) { 93 return ""; 94 } 95 MtpDeviceInfo info = device.getDeviceInfo(); 96 if (info == null) { 97 return ""; 98 } 99 String manufacturer = info.getManufacturer().trim(); 100 String model = info.getModel().trim(); 101 return manufacturer + " " + model; 102 } 103 104 @Override getSubMediaSet(int index)105 public MediaSet getSubMediaSet(int index) { 106 return index < mDeviceSet.size() ? mDeviceSet.get(index) : null; 107 } 108 109 @Override getSubMediaSetCount()110 public int getSubMediaSetCount() { 111 return mDeviceSet.size(); 112 } 113 114 @Override getName()115 public String getName() { 116 return mName; 117 } 118 119 @Override isLoading()120 public synchronized boolean isLoading() { 121 return mIsLoading; 122 } 123 124 @Override reload()125 public synchronized long reload() { 126 if (mNotifier.isDirty()) { 127 if (mLoadTask != null) mLoadTask.cancel(); 128 mIsLoading = true; 129 mLoadTask = mApplication.getThreadPool().submit(new DevicesLoader(), this); 130 } 131 if (mLoadBuffer != null) { 132 mDeviceSet = mLoadBuffer; 133 mLoadBuffer = null; 134 for (MediaSet device : mDeviceSet) { 135 device.reload(); 136 } 137 mDataVersion = nextVersionNumber(); 138 } 139 return mDataVersion; 140 } 141 142 @Override onFutureDone(Future<ArrayList<MediaSet>> future)143 public synchronized void onFutureDone(Future<ArrayList<MediaSet>> future) { 144 if (future != mLoadTask) return; 145 mLoadBuffer = future.get(); 146 mIsLoading = false; 147 if (mLoadBuffer == null) mLoadBuffer = new ArrayList<MediaSet>(); 148 149 mHandler.post(new Runnable() { 150 @Override 151 public void run() { 152 notifyContentChanged(); 153 } 154 }); 155 } 156 } 157