146d0adf8256a42416584765625852b6e48497c90Mike Lockwood/* 246d0adf8256a42416584765625852b6e48497c90Mike Lockwood * Copyright (C) 2011 The Android Open Source Project 346d0adf8256a42416584765625852b6e48497c90Mike Lockwood * 446d0adf8256a42416584765625852b6e48497c90Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 546d0adf8256a42416584765625852b6e48497c90Mike Lockwood * you may not use this file except in compliance with the License. 646d0adf8256a42416584765625852b6e48497c90Mike Lockwood * You may obtain a copy of the License at 746d0adf8256a42416584765625852b6e48497c90Mike Lockwood * 846d0adf8256a42416584765625852b6e48497c90Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 946d0adf8256a42416584765625852b6e48497c90Mike Lockwood * 1046d0adf8256a42416584765625852b6e48497c90Mike Lockwood * Unless required by applicable law or agreed to in writing, software 1146d0adf8256a42416584765625852b6e48497c90Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 1246d0adf8256a42416584765625852b6e48497c90Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1346d0adf8256a42416584765625852b6e48497c90Mike Lockwood * See the License for the specific language governing permissions an 1446d0adf8256a42416584765625852b6e48497c90Mike Lockwood * limitations under the License. 1546d0adf8256a42416584765625852b6e48497c90Mike Lockwood */ 1646d0adf8256a42416584765625852b6e48497c90Mike Lockwood 1746d0adf8256a42416584765625852b6e48497c90Mike Lockwoodpackage com.android.server.usb; 1846d0adf8256a42416584765625852b6e48497c90Mike Lockwood 1946d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.content.Context; 20c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLeanimport android.content.Intent; 217531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwoodimport android.hardware.usb.UsbConfiguration; 2246d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.hardware.usb.UsbConstants; 2346d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.hardware.usb.UsbDevice; 2446d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.hardware.usb.UsbEndpoint; 2546d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.hardware.usb.UsbInterface; 2646d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.os.Bundle; 2746d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.os.ParcelFileDescriptor; 28fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkeyimport android.os.Parcelable; 2946d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.util.Slog; 3046d0adf8256a42416584765625852b6e48497c90Mike Lockwood 318b2c3a14603d163d7564e6f60286995079687690Jeff Sharkeyimport com.android.internal.annotations.GuardedBy; 328b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey 3346d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport java.io.FileDescriptor; 34c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLeanimport java.io.FileNotFoundException; 3546d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport java.io.PrintWriter; 367531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwoodimport java.util.ArrayList; 3746d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport java.util.HashMap; 3846d0adf8256a42416584765625852b6e48497c90Mike Lockwood 3946d0adf8256a42416584765625852b6e48497c90Mike Lockwood/** 4046d0adf8256a42416584765625852b6e48497c90Mike Lockwood * UsbHostManager manages USB state in host mode. 4146d0adf8256a42416584765625852b6e48497c90Mike Lockwood */ 4246d0adf8256a42416584765625852b6e48497c90Mike Lockwoodpublic class UsbHostManager { 4346d0adf8256a42416584765625852b6e48497c90Mike Lockwood private static final String TAG = UsbHostManager.class.getSimpleName(); 443d50308c7fd2a40dfdeeecdacd44b6ae6d28aafbMike Lockwood private static final boolean DEBUG = false; 4546d0adf8256a42416584765625852b6e48497c90Mike Lockwood 4646d0adf8256a42416584765625852b6e48497c90Mike Lockwood // contains all connected USB devices 47fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey private final HashMap<String, UsbDevice> mDevices = new HashMap<String, UsbDevice>(); 4846d0adf8256a42416584765625852b6e48497c90Mike Lockwood 493d50308c7fd2a40dfdeeecdacd44b6ae6d28aafbMike Lockwood 5046d0adf8256a42416584765625852b6e48497c90Mike Lockwood // USB busses to exclude from USB host support 5146d0adf8256a42416584765625852b6e48497c90Mike Lockwood private final String[] mHostBlacklist; 5246d0adf8256a42416584765625852b6e48497c90Mike Lockwood 5346d0adf8256a42416584765625852b6e48497c90Mike Lockwood private final Context mContext; 5446d0adf8256a42416584765625852b6e48497c90Mike Lockwood private final Object mLock = new Object(); 5546d0adf8256a42416584765625852b6e48497c90Mike Lockwood 567531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood private UsbDevice mNewDevice; 577531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood private UsbConfiguration mNewConfiguration; 587531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood private UsbInterface mNewInterface; 597531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood private ArrayList<UsbConfiguration> mNewConfigurations; 607531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood private ArrayList<UsbInterface> mNewInterfaces; 617531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood private ArrayList<UsbEndpoint> mNewEndpoints; 627531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood 633d50308c7fd2a40dfdeeecdacd44b6ae6d28aafbMike Lockwood private UsbAudioManager mUsbAudioManager; 64df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean 658b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey @GuardedBy("mLock") 66fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey private UsbSettingsManager mCurrentSettings; 67fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey 68fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey public UsbHostManager(Context context) { 6946d0adf8256a42416584765625852b6e48497c90Mike Lockwood mContext = context; 7046d0adf8256a42416584765625852b6e48497c90Mike Lockwood mHostBlacklist = context.getResources().getStringArray( 7146d0adf8256a42416584765625852b6e48497c90Mike Lockwood com.android.internal.R.array.config_usbHostBlacklist); 723d50308c7fd2a40dfdeeecdacd44b6ae6d28aafbMike Lockwood mUsbAudioManager = new UsbAudioManager(context); 7346d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 7446d0adf8256a42416584765625852b6e48497c90Mike Lockwood 75fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey public void setCurrentSettings(UsbSettingsManager settings) { 76fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey synchronized (mLock) { 77fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey mCurrentSettings = settings; 78fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey } 79fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey } 80fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey 81fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey private UsbSettingsManager getCurrentSettings() { 82fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey synchronized (mLock) { 83fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey return mCurrentSettings; 84fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey } 85fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey } 86fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey 8746d0adf8256a42416584765625852b6e48497c90Mike Lockwood private boolean isBlackListed(String deviceName) { 8846d0adf8256a42416584765625852b6e48497c90Mike Lockwood int count = mHostBlacklist.length; 8946d0adf8256a42416584765625852b6e48497c90Mike Lockwood for (int i = 0; i < count; i++) { 9046d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (deviceName.startsWith(mHostBlacklist[i])) { 9146d0adf8256a42416584765625852b6e48497c90Mike Lockwood return true; 9246d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 9346d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 9446d0adf8256a42416584765625852b6e48497c90Mike Lockwood return false; 9546d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 9646d0adf8256a42416584765625852b6e48497c90Mike Lockwood 9746d0adf8256a42416584765625852b6e48497c90Mike Lockwood /* returns true if the USB device should not be accessible by applications */ 9846d0adf8256a42416584765625852b6e48497c90Mike Lockwood private boolean isBlackListed(int clazz, int subClass, int protocol) { 9946d0adf8256a42416584765625852b6e48497c90Mike Lockwood // blacklist hubs 10046d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (clazz == UsbConstants.USB_CLASS_HUB) return true; 10146d0adf8256a42416584765625852b6e48497c90Mike Lockwood 10246d0adf8256a42416584765625852b6e48497c90Mike Lockwood // blacklist HID boot devices (mouse and keyboard) 10346d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (clazz == UsbConstants.USB_CLASS_HID && 10446d0adf8256a42416584765625852b6e48497c90Mike Lockwood subClass == UsbConstants.USB_INTERFACE_SUBCLASS_BOOT) { 10546d0adf8256a42416584765625852b6e48497c90Mike Lockwood return true; 10646d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 10746d0adf8256a42416584765625852b6e48497c90Mike Lockwood 10846d0adf8256a42416584765625852b6e48497c90Mike Lockwood return false; 10946d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 11046d0adf8256a42416584765625852b6e48497c90Mike Lockwood 1117531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood /* Called from JNI in monitorUsbHostBus() to report new USB devices 1127531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood Returns true if successful, in which case the JNI code will continue adding configurations, 1137531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood interfaces and endpoints, and finally call endUsbDeviceAdded after all descriptors 1147531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood have been processed 1157531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood */ 1167531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood private boolean beginUsbDeviceAdded(String deviceName, int vendorID, int productID, 11746d0adf8256a42416584765625852b6e48497c90Mike Lockwood int deviceClass, int deviceSubclass, int deviceProtocol, 1187531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood String manufacturerName, String productName, String serialNumber) { 11946d0adf8256a42416584765625852b6e48497c90Mike Lockwood 1203d50308c7fd2a40dfdeeecdacd44b6ae6d28aafbMike Lockwood if (DEBUG) { 121df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean Slog.d(TAG, "usb:UsbHostManager.beginUsbDeviceAdded(" + deviceName + ")"); 122df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean // Audio Class Codes: 123df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean // Audio: 0x01 124df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean // Audio Subclass Codes: 125df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean // undefined: 0x00 126df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean // audio control: 0x01 127df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean // audio streaming: 0x02 128df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean // midi streaming: 0x03 129df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean 130df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean // some useful debugging info 131df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean Slog.d(TAG, "usb: nm:" + deviceName + " vnd:" + vendorID + " prd:" + productID + " cls:" 132df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean + deviceClass + " sub:" + deviceSubclass + " proto:" + deviceProtocol); 133c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean } 134c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean 135df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean // OK this is non-obvious, but true. One can't tell if the device being attached is even 136df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean // potentially an audio device without parsing the interface descriptors, so punt on any 137df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean // such test until endUsbDeviceAdded() when we have that info. 138df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean 13946d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (isBlackListed(deviceName) || 14046d0adf8256a42416584765625852b6e48497c90Mike Lockwood isBlackListed(deviceClass, deviceSubclass, deviceProtocol)) { 1417531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood return false; 14246d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 14346d0adf8256a42416584765625852b6e48497c90Mike Lockwood 14446d0adf8256a42416584765625852b6e48497c90Mike Lockwood synchronized (mLock) { 14546d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (mDevices.get(deviceName) != null) { 146fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood Slog.w(TAG, "device already on mDevices list: " + deviceName); 1477531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood return false; 14846d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 14946d0adf8256a42416584765625852b6e48497c90Mike Lockwood 1507531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood if (mNewDevice != null) { 1517531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood Slog.e(TAG, "mNewDevice is not null in endUsbDeviceAdded"); 1527531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood return false; 15346d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 15446d0adf8256a42416584765625852b6e48497c90Mike Lockwood 1557531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewDevice = new UsbDevice(deviceName, vendorID, productID, 156575ca85c147f1521480ea98aca13aa3b1ec38884Robin Cutshaw deviceClass, deviceSubclass, deviceProtocol, 1577531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood manufacturerName, productName, serialNumber); 1587531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood 1597531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewConfigurations = new ArrayList<UsbConfiguration>(); 1607531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewInterfaces = new ArrayList<UsbInterface>(); 1617531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewEndpoints = new ArrayList<UsbEndpoint>(); 1627531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood } 163df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean 1647531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood return true; 1657531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood } 1667531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood 1677531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood /* Called from JNI in monitorUsbHostBus() to report new USB configuration for the device 1687531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood currently being added. Returns true if successful, false in case of error. 1697531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood */ 1707531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood private void addUsbConfiguration(int id, String name, int attributes, int maxPower) { 1717531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood if (mNewConfiguration != null) { 1727531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewConfiguration.setInterfaces( 1737531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewInterfaces.toArray(new UsbInterface[mNewInterfaces.size()])); 1747531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewInterfaces.clear(); 1757531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood } 1767531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood 1777531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewConfiguration = new UsbConfiguration(id, name, attributes, maxPower); 1787531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewConfigurations.add(mNewConfiguration); 1797531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood } 1807531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood 1817531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood /* Called from JNI in monitorUsbHostBus() to report new USB interface for the device 1827531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood currently being added. Returns true if successful, false in case of error. 1837531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood */ 1847531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood private void addUsbInterface(int id, String name, int altSetting, 1857531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood int Class, int subClass, int protocol) { 1867531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood if (mNewInterface != null) { 1877531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewInterface.setEndpoints( 1887531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewEndpoints.toArray(new UsbEndpoint[mNewEndpoints.size()])); 1897531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewEndpoints.clear(); 1907531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood } 1917531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood 1927531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewInterface = new UsbInterface(id, altSetting, name, Class, subClass, protocol); 1937531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewInterfaces.add(mNewInterface); 1947531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood } 1957531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood 1967531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood /* Called from JNI in monitorUsbHostBus() to report new USB endpoint for the device 1977531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood currently being added. Returns true if successful, false in case of error. 1987531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood */ 1997531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood private void addUsbEndpoint(int address, int attributes, int maxPacketSize, int interval) { 2007531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewEndpoints.add(new UsbEndpoint(address, attributes, maxPacketSize, interval)); 2017531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood } 2027531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood 2037531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood /* Called from JNI in monitorUsbHostBus() to finish adding a new device */ 2047531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood private void endUsbDeviceAdded() { 2053d50308c7fd2a40dfdeeecdacd44b6ae6d28aafbMike Lockwood if (DEBUG) { 206c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean Slog.d(TAG, "usb:UsbHostManager.endUsbDeviceAdded()"); 207c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean } 2087531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood if (mNewInterface != null) { 2097531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewInterface.setEndpoints( 2107531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewEndpoints.toArray(new UsbEndpoint[mNewEndpoints.size()])); 2117531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood } 2127531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood if (mNewConfiguration != null) { 2137531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewConfiguration.setInterfaces( 2147531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewInterfaces.toArray(new UsbInterface[mNewInterfaces.size()])); 2157531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood } 2167531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood 217df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean 2187531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood synchronized (mLock) { 2197531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood if (mNewDevice != null) { 2207531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewDevice.setConfigurations( 2217531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewConfigurations.toArray(new UsbConfiguration[mNewConfigurations.size()])); 2227531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mDevices.put(mNewDevice.getDeviceName(), mNewDevice); 2237531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood Slog.d(TAG, "Added device " + mNewDevice); 2247531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood getCurrentSettings().deviceAttached(mNewDevice); 2253d50308c7fd2a40dfdeeecdacd44b6ae6d28aafbMike Lockwood mUsbAudioManager.deviceAdded(mNewDevice); 2267531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood } else { 2277531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood Slog.e(TAG, "mNewDevice is null in endUsbDeviceAdded"); 2287531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood } 2297531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewDevice = null; 2307531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewConfigurations = null; 2317531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewInterfaces = null; 2327531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood mNewEndpoints = null; 23346d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 23446d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 23546d0adf8256a42416584765625852b6e48497c90Mike Lockwood 23646d0adf8256a42416584765625852b6e48497c90Mike Lockwood /* Called from JNI in monitorUsbHostBus to report USB device removal */ 23746d0adf8256a42416584765625852b6e48497c90Mike Lockwood private void usbDeviceRemoved(String deviceName) { 23846d0adf8256a42416584765625852b6e48497c90Mike Lockwood synchronized (mLock) { 23946d0adf8256a42416584765625852b6e48497c90Mike Lockwood UsbDevice device = mDevices.remove(deviceName); 24046d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (device != null) { 2413d50308c7fd2a40dfdeeecdacd44b6ae6d28aafbMike Lockwood mUsbAudioManager.deviceRemoved(device); 242fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey getCurrentSettings().deviceDetached(device); 24346d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 24446d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 24546d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 24646d0adf8256a42416584765625852b6e48497c90Mike Lockwood 24746d0adf8256a42416584765625852b6e48497c90Mike Lockwood public void systemReady() { 24846d0adf8256a42416584765625852b6e48497c90Mike Lockwood synchronized (mLock) { 24946d0adf8256a42416584765625852b6e48497c90Mike Lockwood // Create a thread to call into native code to wait for USB host events. 25046d0adf8256a42416584765625852b6e48497c90Mike Lockwood // This thread will call us back on usbDeviceAdded and usbDeviceRemoved. 25146d0adf8256a42416584765625852b6e48497c90Mike Lockwood Runnable runnable = new Runnable() { 25246d0adf8256a42416584765625852b6e48497c90Mike Lockwood public void run() { 25346d0adf8256a42416584765625852b6e48497c90Mike Lockwood monitorUsbHostBus(); 25446d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 25546d0adf8256a42416584765625852b6e48497c90Mike Lockwood }; 25646d0adf8256a42416584765625852b6e48497c90Mike Lockwood new Thread(null, runnable, "UsbService host thread").start(); 25746d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 25846d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 25946d0adf8256a42416584765625852b6e48497c90Mike Lockwood 26046d0adf8256a42416584765625852b6e48497c90Mike Lockwood /* Returns a list of all currently attached USB devices */ 26146d0adf8256a42416584765625852b6e48497c90Mike Lockwood public void getDeviceList(Bundle devices) { 26246d0adf8256a42416584765625852b6e48497c90Mike Lockwood synchronized (mLock) { 26346d0adf8256a42416584765625852b6e48497c90Mike Lockwood for (String name : mDevices.keySet()) { 26446d0adf8256a42416584765625852b6e48497c90Mike Lockwood devices.putParcelable(name, mDevices.get(name)); 26546d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 26646d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 26746d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 26846d0adf8256a42416584765625852b6e48497c90Mike Lockwood 26946d0adf8256a42416584765625852b6e48497c90Mike Lockwood /* Opens the specified USB device */ 27046d0adf8256a42416584765625852b6e48497c90Mike Lockwood public ParcelFileDescriptor openDevice(String deviceName) { 27146d0adf8256a42416584765625852b6e48497c90Mike Lockwood synchronized (mLock) { 27246d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (isBlackListed(deviceName)) { 27346d0adf8256a42416584765625852b6e48497c90Mike Lockwood throw new SecurityException("USB device is on a restricted bus"); 27446d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 27546d0adf8256a42416584765625852b6e48497c90Mike Lockwood UsbDevice device = mDevices.get(deviceName); 27646d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (device == null) { 27746d0adf8256a42416584765625852b6e48497c90Mike Lockwood // if it is not in mDevices, it either does not exist or is blacklisted 27846d0adf8256a42416584765625852b6e48497c90Mike Lockwood throw new IllegalArgumentException( 27946d0adf8256a42416584765625852b6e48497c90Mike Lockwood "device " + deviceName + " does not exist or is restricted"); 28046d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 281fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey getCurrentSettings().checkPermission(device); 28246d0adf8256a42416584765625852b6e48497c90Mike Lockwood return nativeOpenDevice(deviceName); 28346d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 28446d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 28546d0adf8256a42416584765625852b6e48497c90Mike Lockwood 28646d0adf8256a42416584765625852b6e48497c90Mike Lockwood public void dump(FileDescriptor fd, PrintWriter pw) { 28746d0adf8256a42416584765625852b6e48497c90Mike Lockwood synchronized (mLock) { 28846d0adf8256a42416584765625852b6e48497c90Mike Lockwood pw.println(" USB Host State:"); 28946d0adf8256a42416584765625852b6e48497c90Mike Lockwood for (String name : mDevices.keySet()) { 29046d0adf8256a42416584765625852b6e48497c90Mike Lockwood pw.println(" " + name + ": " + mDevices.get(name)); 29146d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 29246d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 2933d50308c7fd2a40dfdeeecdacd44b6ae6d28aafbMike Lockwood mUsbAudioManager.dump(fd, pw); 29446d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 29546d0adf8256a42416584765625852b6e48497c90Mike Lockwood 29646d0adf8256a42416584765625852b6e48497c90Mike Lockwood private native void monitorUsbHostBus(); 29746d0adf8256a42416584765625852b6e48497c90Mike Lockwood private native ParcelFileDescriptor nativeOpenDevice(String deviceName); 29846d0adf8256a42416584765625852b6e48497c90Mike Lockwood} 299