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