| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.mtp; |
| |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.hardware.UsbConstants; |
| import android.hardware.UsbDevice; |
| import android.hardware.UsbInterface; |
| import android.hardware.UsbManager; |
| import android.os.ParcelFileDescriptor; |
| import android.util.Log; |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * This class helps an application manage a list of connected MTP devices. |
| * It listens for MTP devices being attached and removed from the USB host bus |
| * and notifies the application when the MTP device list changes. |
| * {@hide} |
| */ |
| public class MtpClient { |
| |
| private static final String TAG = "MtpClient"; |
| |
| private final Context mContext; |
| private final UsbManager mUsbManager; |
| private final ArrayList<Listener> mListeners = new ArrayList<Listener>(); |
| private final ArrayList<MtpDevice> mDeviceList = new ArrayList<MtpDevice>(); |
| |
| private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| String deviceName = intent.getStringExtra(UsbManager.EXTRA_DEVICE_NAME); |
| |
| synchronized (mDeviceList) { |
| MtpDevice mtpDevice = getDeviceLocked(deviceName); |
| |
| if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) { |
| if (mtpDevice == null) { |
| UsbDevice usbDevice = |
| (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); |
| mtpDevice = openDevice(usbDevice); |
| } |
| if (mtpDevice != null) { |
| mDeviceList.add(mtpDevice); |
| for (Listener listener : mListeners) { |
| listener.deviceAdded(mtpDevice); |
| } |
| } |
| } else if (mtpDevice != null) { |
| mDeviceList.remove(mtpDevice); |
| for (Listener listener : mListeners) { |
| listener.deviceRemoved(mtpDevice); |
| } |
| } |
| } |
| } |
| }; |
| |
| public interface Listener { |
| public void deviceAdded(MtpDevice device); |
| public void deviceRemoved(MtpDevice device); |
| } |
| |
| static public boolean isCamera(UsbDevice device) { |
| int count = device.getInterfaceCount(); |
| for (int i = 0; i < count; i++) { |
| UsbInterface intf = device.getInterface(i); |
| if (intf.getInterfaceClass() == UsbConstants.USB_CLASS_STILL_IMAGE && |
| intf.getInterfaceSubclass() == 1 && |
| intf.getInterfaceProtocol() == 1) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private MtpDevice openDevice(UsbDevice usbDevice) { |
| if (isCamera(usbDevice)) { |
| MtpDevice mtpDevice = new MtpDevice(usbDevice); |
| if (mtpDevice.open(mUsbManager)) { |
| return mtpDevice; |
| } |
| } |
| return null; |
| } |
| |
| public MtpClient(Context context) { |
| mContext = context; |
| mUsbManager = (UsbManager)context.getSystemService(Context.USB_SERVICE); |
| |
| IntentFilter filter = new IntentFilter(); |
| filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); |
| filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); |
| context.registerReceiver(mUsbReceiver, filter); |
| |
| for (UsbDevice usbDevice : mUsbManager.getDeviceList().values()) { |
| MtpDevice mtpDevice = getDeviceLocked(usbDevice.getDeviceName()); |
| if (mtpDevice == null) { |
| mtpDevice = openDevice(usbDevice); |
| } |
| if (mtpDevice != null) { |
| mDeviceList.add(mtpDevice); |
| } |
| } |
| } |
| |
| public void close() { |
| mContext.unregisterReceiver(mUsbReceiver); |
| } |
| |
| @Override |
| protected void finalize() throws Throwable { |
| try { |
| close(); |
| } finally { |
| super.finalize(); |
| } |
| } |
| |
| public void addListener(Listener listener) { |
| synchronized (mDeviceList) { |
| if (!mListeners.contains(listener)) { |
| mListeners.add(listener); |
| } |
| } |
| } |
| |
| public void removeListener(Listener listener) { |
| synchronized (mDeviceList) { |
| mListeners.remove(listener); |
| } |
| } |
| |
| public MtpDevice getDevice(String deviceName) { |
| synchronized (mDeviceList) { |
| return getDeviceLocked(deviceName); |
| } |
| } |
| |
| public MtpDevice getDevice(int id) { |
| synchronized (mDeviceList) { |
| return getDeviceLocked(UsbDevice.getDeviceName(id)); |
| } |
| } |
| |
| private MtpDevice getDeviceLocked(String deviceName) { |
| for (MtpDevice device : mDeviceList) { |
| if (device.getDeviceName().equals(deviceName)) { |
| return device; |
| } |
| } |
| return null; |
| } |
| |
| public List<MtpDevice> getDeviceList() { |
| synchronized (mDeviceList) { |
| return new ArrayList<MtpDevice>(mDeviceList); |
| } |
| } |
| |
| public List<MtpStorageInfo> getStorageList(String deviceName) { |
| MtpDevice device = getDevice(deviceName); |
| if (device == null) { |
| return null; |
| } |
| int[] storageIds = device.getStorageIds(); |
| if (storageIds == null) { |
| return null; |
| } |
| |
| int length = storageIds.length; |
| ArrayList<MtpStorageInfo> storageList = new ArrayList<MtpStorageInfo>(length); |
| for (int i = 0; i < length; i++) { |
| MtpStorageInfo info = device.getStorageInfo(storageIds[i]); |
| if (info == null) { |
| Log.w(TAG, "getStorageInfo failed"); |
| } else { |
| storageList.add(info); |
| } |
| } |
| return storageList; |
| } |
| |
| public MtpObjectInfo getObjectInfo(String deviceName, int objectHandle) { |
| MtpDevice device = getDevice(deviceName); |
| if (device == null) { |
| return null; |
| } |
| return device.getObjectInfo(objectHandle); |
| } |
| |
| public boolean deleteObject(String deviceName, int objectHandle) { |
| MtpDevice device = getDevice(deviceName); |
| if (device == null) { |
| return false; |
| } |
| return device.deleteObject(objectHandle); |
| } |
| |
| public List<MtpObjectInfo> getObjectList(String deviceName, int storageId, int objectHandle) { |
| MtpDevice device = getDevice(deviceName); |
| if (device == null) { |
| return null; |
| } |
| if (objectHandle == 0) { |
| // all objects in root of storage |
| objectHandle = 0xFFFFFFFF; |
| } |
| int[] handles = device.getObjectHandles(storageId, 0, objectHandle); |
| if (handles == null) { |
| return null; |
| } |
| |
| int length = handles.length; |
| ArrayList<MtpObjectInfo> objectList = new ArrayList<MtpObjectInfo>(length); |
| for (int i = 0; i < length; i++) { |
| MtpObjectInfo info = device.getObjectInfo(handles[i]); |
| if (info == null) { |
| Log.w(TAG, "getObjectInfo failed"); |
| } else { |
| objectList.add(info); |
| } |
| } |
| return objectList; |
| } |
| |
| public byte[] getObject(String deviceName, int objectHandle, int objectSize) { |
| MtpDevice device = getDevice(deviceName); |
| if (device == null) { |
| return null; |
| } |
| return device.getObject(objectHandle, objectSize); |
| } |
| |
| public byte[] getThumbnail(String deviceName, int objectHandle) { |
| MtpDevice device = getDevice(deviceName); |
| if (device == null) { |
| return null; |
| } |
| return device.getThumbnail(objectHandle); |
| } |
| |
| public boolean importFile(String deviceName, int objectHandle, String destPath) { |
| MtpDevice device = getDevice(deviceName); |
| if (device == null) { |
| return false; |
| } |
| return device.importFile(objectHandle, destPath); |
| } |
| } |