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;
207531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwoodimport android.hardware.usb.UsbConfiguration;
2146d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.hardware.usb.UsbConstants;
2246d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.hardware.usb.UsbDevice;
2346d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.hardware.usb.UsbEndpoint;
2446d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.hardware.usb.UsbInterface;
2546d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.os.Bundle;
2646d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.os.ParcelFileDescriptor;
2746d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport android.util.Slog;
2846d0adf8256a42416584765625852b6e48497c90Mike Lockwood
298b2c3a14603d163d7564e6f60286995079687690Jeff Sharkeyimport com.android.internal.annotations.GuardedBy;
302dbccc1926ea2d3e27c5cfd2d61d2b3d5ed787c0Jeff Brownimport com.android.internal.util.IndentingPrintWriter;
318b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey
3246d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport java.io.FileDescriptor;
3346d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport java.io.PrintWriter;
347531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwoodimport java.util.ArrayList;
3546d0adf8256a42416584765625852b6e48497c90Mike Lockwoodimport java.util.HashMap;
3646d0adf8256a42416584765625852b6e48497c90Mike Lockwood
3746d0adf8256a42416584765625852b6e48497c90Mike Lockwood/**
3846d0adf8256a42416584765625852b6e48497c90Mike Lockwood * UsbHostManager manages USB state in host mode.
3946d0adf8256a42416584765625852b6e48497c90Mike Lockwood */
4046d0adf8256a42416584765625852b6e48497c90Mike Lockwoodpublic class UsbHostManager {
4146d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private static final String TAG = UsbHostManager.class.getSimpleName();
423d50308c7fd2a40dfdeeecdacd44b6ae6d28aafbMike Lockwood    private static final boolean DEBUG = false;
4346d0adf8256a42416584765625852b6e48497c90Mike Lockwood
4446d0adf8256a42416584765625852b6e48497c90Mike Lockwood    // contains all connected USB devices
45fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    private final HashMap<String, UsbDevice> mDevices = new HashMap<String, UsbDevice>();
4646d0adf8256a42416584765625852b6e48497c90Mike Lockwood
473d50308c7fd2a40dfdeeecdacd44b6ae6d28aafbMike Lockwood
4846d0adf8256a42416584765625852b6e48497c90Mike Lockwood    // USB busses to exclude from USB host support
4946d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private final String[] mHostBlacklist;
5046d0adf8256a42416584765625852b6e48497c90Mike Lockwood
5146d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private final Context mContext;
5246d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private final Object mLock = new Object();
5346d0adf8256a42416584765625852b6e48497c90Mike Lockwood
547531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    private UsbDevice mNewDevice;
557531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    private UsbConfiguration mNewConfiguration;
567531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    private UsbInterface mNewInterface;
577531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    private ArrayList<UsbConfiguration> mNewConfigurations;
587531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    private ArrayList<UsbInterface> mNewInterfaces;
597531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    private ArrayList<UsbEndpoint> mNewEndpoints;
607531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood
612e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood    private final UsbAlsaManager mUsbAlsaManager;
62df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean
638b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey    @GuardedBy("mLock")
64fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    private UsbSettingsManager mCurrentSettings;
65fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
662e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood    public UsbHostManager(Context context, UsbAlsaManager alsaManager) {
6746d0adf8256a42416584765625852b6e48497c90Mike Lockwood        mContext = context;
6846d0adf8256a42416584765625852b6e48497c90Mike Lockwood        mHostBlacklist = context.getResources().getStringArray(
6946d0adf8256a42416584765625852b6e48497c90Mike Lockwood                com.android.internal.R.array.config_usbHostBlacklist);
702e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood        mUsbAlsaManager = alsaManager;
7146d0adf8256a42416584765625852b6e48497c90Mike Lockwood    }
7246d0adf8256a42416584765625852b6e48497c90Mike Lockwood
73fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    public void setCurrentSettings(UsbSettingsManager settings) {
74fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        synchronized (mLock) {
75fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            mCurrentSettings = settings;
76fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        }
77fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    }
78fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
79fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    private UsbSettingsManager getCurrentSettings() {
80fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        synchronized (mLock) {
81fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            return mCurrentSettings;
82fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey        }
83fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey    }
84fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey
8546d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private boolean isBlackListed(String deviceName) {
8646d0adf8256a42416584765625852b6e48497c90Mike Lockwood        int count = mHostBlacklist.length;
8746d0adf8256a42416584765625852b6e48497c90Mike Lockwood        for (int i = 0; i < count; i++) {
8846d0adf8256a42416584765625852b6e48497c90Mike Lockwood            if (deviceName.startsWith(mHostBlacklist[i])) {
8946d0adf8256a42416584765625852b6e48497c90Mike Lockwood                return true;
9046d0adf8256a42416584765625852b6e48497c90Mike Lockwood            }
9146d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
9246d0adf8256a42416584765625852b6e48497c90Mike Lockwood        return false;
9346d0adf8256a42416584765625852b6e48497c90Mike Lockwood    }
9446d0adf8256a42416584765625852b6e48497c90Mike Lockwood
9546d0adf8256a42416584765625852b6e48497c90Mike Lockwood    /* returns true if the USB device should not be accessible by applications */
9646d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private boolean isBlackListed(int clazz, int subClass, int protocol) {
9746d0adf8256a42416584765625852b6e48497c90Mike Lockwood        // blacklist hubs
9846d0adf8256a42416584765625852b6e48497c90Mike Lockwood        if (clazz == UsbConstants.USB_CLASS_HUB) return true;
9946d0adf8256a42416584765625852b6e48497c90Mike Lockwood
10046d0adf8256a42416584765625852b6e48497c90Mike Lockwood        // blacklist HID boot devices (mouse and keyboard)
10146d0adf8256a42416584765625852b6e48497c90Mike Lockwood        if (clazz == UsbConstants.USB_CLASS_HID &&
10246d0adf8256a42416584765625852b6e48497c90Mike Lockwood                subClass == UsbConstants.USB_INTERFACE_SUBCLASS_BOOT) {
10346d0adf8256a42416584765625852b6e48497c90Mike Lockwood            return true;
10446d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
10546d0adf8256a42416584765625852b6e48497c90Mike Lockwood
10646d0adf8256a42416584765625852b6e48497c90Mike Lockwood        return false;
10746d0adf8256a42416584765625852b6e48497c90Mike Lockwood    }
10846d0adf8256a42416584765625852b6e48497c90Mike Lockwood
1097531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    /* Called from JNI in monitorUsbHostBus() to report new USB devices
1107531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood       Returns true if successful, in which case the JNI code will continue adding configurations,
1117531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood       interfaces and endpoints, and finally call endUsbDeviceAdded after all descriptors
1127531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood       have been processed
1137531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood     */
1147531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    private boolean beginUsbDeviceAdded(String deviceName, int vendorID, int productID,
11546d0adf8256a42416584765625852b6e48497c90Mike Lockwood            int deviceClass, int deviceSubclass, int deviceProtocol,
116c9bb40ea95101f8a46fab29beac02cc7204be320Mike Lockwood            String manufacturerName, String productName, int version, String serialNumber) {
11746d0adf8256a42416584765625852b6e48497c90Mike Lockwood
1183d50308c7fd2a40dfdeeecdacd44b6ae6d28aafbMike Lockwood        if (DEBUG) {
119df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean            Slog.d(TAG, "usb:UsbHostManager.beginUsbDeviceAdded(" + deviceName + ")");
120df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean            // Audio Class Codes:
121df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean            // Audio: 0x01
122df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean            // Audio Subclass Codes:
123df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean            // undefined: 0x00
124df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean            // audio control: 0x01
125df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean            // audio streaming: 0x02
126df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean            // midi streaming: 0x03
127df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean
128df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean            // some useful debugging info
129df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean            Slog.d(TAG, "usb: nm:" + deviceName + " vnd:" + vendorID + " prd:" + productID + " cls:"
130df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean                    + deviceClass + " sub:" + deviceSubclass + " proto:" + deviceProtocol);
131c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean        }
132c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean
133df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean        // OK this is non-obvious, but true. One can't tell if the device being attached is even
134df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean        // potentially an audio device without parsing the interface descriptors, so punt on any
135df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean        // such test until endUsbDeviceAdded() when we have that info.
136df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean
13746d0adf8256a42416584765625852b6e48497c90Mike Lockwood        if (isBlackListed(deviceName) ||
13846d0adf8256a42416584765625852b6e48497c90Mike Lockwood                isBlackListed(deviceClass, deviceSubclass, deviceProtocol)) {
1397531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            return false;
14046d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
14146d0adf8256a42416584765625852b6e48497c90Mike Lockwood
14246d0adf8256a42416584765625852b6e48497c90Mike Lockwood        synchronized (mLock) {
14346d0adf8256a42416584765625852b6e48497c90Mike Lockwood            if (mDevices.get(deviceName) != null) {
144fdc0c2984d05e32954608f46514c4cbe3a5a9424Mike Lockwood                Slog.w(TAG, "device already on mDevices list: " + deviceName);
1457531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood                return false;
14646d0adf8256a42416584765625852b6e48497c90Mike Lockwood            }
14746d0adf8256a42416584765625852b6e48497c90Mike Lockwood
1487531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            if (mNewDevice != null) {
1497531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood                Slog.e(TAG, "mNewDevice is not null in endUsbDeviceAdded");
1507531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood                return false;
15146d0adf8256a42416584765625852b6e48497c90Mike Lockwood            }
15246d0adf8256a42416584765625852b6e48497c90Mike Lockwood
153c9bb40ea95101f8a46fab29beac02cc7204be320Mike Lockwood            // Create version string in "%.%" format
154c9bb40ea95101f8a46fab29beac02cc7204be320Mike Lockwood            String versionString = Integer.toString(version >> 8) + "." + (version & 0xFF);
155c9bb40ea95101f8a46fab29beac02cc7204be320Mike Lockwood
1567531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            mNewDevice = new UsbDevice(deviceName, vendorID, productID,
157575ca85c147f1521480ea98aca13aa3b1ec38884Robin Cutshaw                    deviceClass, deviceSubclass, deviceProtocol,
158c9bb40ea95101f8a46fab29beac02cc7204be320Mike Lockwood                    manufacturerName, productName, versionString, serialNumber);
1597531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood
1607531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            mNewConfigurations = new ArrayList<UsbConfiguration>();
1617531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            mNewInterfaces = new ArrayList<UsbInterface>();
1627531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            mNewEndpoints = new ArrayList<UsbEndpoint>();
1637531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood        }
164df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean
1657531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood        return true;
1667531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    }
1677531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood
1687531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    /* Called from JNI in monitorUsbHostBus() to report new USB configuration for the device
1697531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood       currently being added.  Returns true if successful, false in case of error.
1707531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood     */
1717531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    private void addUsbConfiguration(int id, String name, int attributes, int maxPower) {
1727531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood        if (mNewConfiguration != null) {
1737531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            mNewConfiguration.setInterfaces(
1747531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood                    mNewInterfaces.toArray(new UsbInterface[mNewInterfaces.size()]));
1757531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            mNewInterfaces.clear();
1767531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood        }
1777531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood
1787531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood        mNewConfiguration = new UsbConfiguration(id, name, attributes, maxPower);
1797531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood        mNewConfigurations.add(mNewConfiguration);
1807531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    }
1817531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood
1827531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    /* Called from JNI in monitorUsbHostBus() to report new USB interface for the device
1837531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood       currently being added.  Returns true if successful, false in case of error.
1847531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood     */
1857531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    private void addUsbInterface(int id, String name, int altSetting,
1867531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            int Class, int subClass, int protocol) {
1877531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood        if (mNewInterface != null) {
1887531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            mNewInterface.setEndpoints(
1897531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood                    mNewEndpoints.toArray(new UsbEndpoint[mNewEndpoints.size()]));
1907531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            mNewEndpoints.clear();
1917531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood        }
1927531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood
1937531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood        mNewInterface = new UsbInterface(id, altSetting, name, Class, subClass, protocol);
1947531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood        mNewInterfaces.add(mNewInterface);
1957531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    }
1967531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood
1977531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    /* Called from JNI in monitorUsbHostBus() to report new USB endpoint for the device
1987531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood       currently being added.  Returns true if successful, false in case of error.
1997531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood     */
2007531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    private void addUsbEndpoint(int address, int attributes, int maxPacketSize, int interval) {
2017531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood        mNewEndpoints.add(new UsbEndpoint(address, attributes, maxPacketSize, interval));
2027531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    }
2037531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood
2047531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    /* Called from JNI in monitorUsbHostBus() to finish adding a new device */
2057531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood    private void endUsbDeviceAdded() {
2063d50308c7fd2a40dfdeeecdacd44b6ae6d28aafbMike Lockwood        if (DEBUG) {
207c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean            Slog.d(TAG, "usb:UsbHostManager.endUsbDeviceAdded()");
208c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean        }
2097531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood        if (mNewInterface != null) {
2107531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            mNewInterface.setEndpoints(
2117531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood                    mNewEndpoints.toArray(new UsbEndpoint[mNewEndpoints.size()]));
2127531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood        }
2137531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood        if (mNewConfiguration != null) {
2147531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            mNewConfiguration.setInterfaces(
2157531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood                    mNewInterfaces.toArray(new UsbInterface[mNewInterfaces.size()]));
2167531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood        }
2177531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood
218df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean
2197531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood        synchronized (mLock) {
2207531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            if (mNewDevice != null) {
2217531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood                mNewDevice.setConfigurations(
2227531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood                        mNewConfigurations.toArray(new UsbConfiguration[mNewConfigurations.size()]));
2237531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood                mDevices.put(mNewDevice.getDeviceName(), mNewDevice);
2247531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood                Slog.d(TAG, "Added device " + mNewDevice);
2257531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood                getCurrentSettings().deviceAttached(mNewDevice);
2262e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood                mUsbAlsaManager.usbDeviceAdded(mNewDevice);
2277531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            } else {
2287531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood                Slog.e(TAG, "mNewDevice is null in endUsbDeviceAdded");
2297531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            }
2307531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            mNewDevice = null;
2317531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            mNewConfigurations = null;
2327531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            mNewInterfaces = null;
2337531aa22355cf03f51def61ba67f1636bf85f408Mike Lockwood            mNewEndpoints = null;
234ed987a52a2aa028814ecc73dd6d60244ac1df7f5wang.zhenyu            mNewConfiguration = null;
235ed987a52a2aa028814ecc73dd6d60244ac1df7f5wang.zhenyu            mNewInterface = null;
23646d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
23746d0adf8256a42416584765625852b6e48497c90Mike Lockwood    }
23846d0adf8256a42416584765625852b6e48497c90Mike Lockwood
23946d0adf8256a42416584765625852b6e48497c90Mike Lockwood    /* Called from JNI in monitorUsbHostBus to report USB device removal */
24046d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private void usbDeviceRemoved(String deviceName) {
24146d0adf8256a42416584765625852b6e48497c90Mike Lockwood        synchronized (mLock) {
24246d0adf8256a42416584765625852b6e48497c90Mike Lockwood            UsbDevice device = mDevices.remove(deviceName);
24346d0adf8256a42416584765625852b6e48497c90Mike Lockwood            if (device != null) {
2442e3434149e00f921ca3555ae55cba04d3c64eeb1Mike Lockwood                mUsbAlsaManager.usbDeviceRemoved(device);
245fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey                getCurrentSettings().deviceDetached(device);
24646d0adf8256a42416584765625852b6e48497c90Mike Lockwood            }
24746d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
24846d0adf8256a42416584765625852b6e48497c90Mike Lockwood    }
24946d0adf8256a42416584765625852b6e48497c90Mike Lockwood
25046d0adf8256a42416584765625852b6e48497c90Mike Lockwood    public void systemReady() {
25146d0adf8256a42416584765625852b6e48497c90Mike Lockwood        synchronized (mLock) {
25246d0adf8256a42416584765625852b6e48497c90Mike Lockwood            // Create a thread to call into native code to wait for USB host events.
25346d0adf8256a42416584765625852b6e48497c90Mike Lockwood            // This thread will call us back on usbDeviceAdded and usbDeviceRemoved.
25446d0adf8256a42416584765625852b6e48497c90Mike Lockwood            Runnable runnable = new Runnable() {
25546d0adf8256a42416584765625852b6e48497c90Mike Lockwood                public void run() {
25646d0adf8256a42416584765625852b6e48497c90Mike Lockwood                    monitorUsbHostBus();
25746d0adf8256a42416584765625852b6e48497c90Mike Lockwood                }
25846d0adf8256a42416584765625852b6e48497c90Mike Lockwood            };
25946d0adf8256a42416584765625852b6e48497c90Mike Lockwood            new Thread(null, runnable, "UsbService host thread").start();
26046d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
26146d0adf8256a42416584765625852b6e48497c90Mike Lockwood    }
26246d0adf8256a42416584765625852b6e48497c90Mike Lockwood
26346d0adf8256a42416584765625852b6e48497c90Mike Lockwood    /* Returns a list of all currently attached USB devices */
26446d0adf8256a42416584765625852b6e48497c90Mike Lockwood    public void getDeviceList(Bundle devices) {
26546d0adf8256a42416584765625852b6e48497c90Mike Lockwood        synchronized (mLock) {
26646d0adf8256a42416584765625852b6e48497c90Mike Lockwood            for (String name : mDevices.keySet()) {
26746d0adf8256a42416584765625852b6e48497c90Mike Lockwood                devices.putParcelable(name, mDevices.get(name));
26846d0adf8256a42416584765625852b6e48497c90Mike Lockwood            }
26946d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
27046d0adf8256a42416584765625852b6e48497c90Mike Lockwood    }
27146d0adf8256a42416584765625852b6e48497c90Mike Lockwood
27246d0adf8256a42416584765625852b6e48497c90Mike Lockwood    /* Opens the specified USB device */
27346d0adf8256a42416584765625852b6e48497c90Mike Lockwood    public ParcelFileDescriptor openDevice(String deviceName) {
27446d0adf8256a42416584765625852b6e48497c90Mike Lockwood        synchronized (mLock) {
27546d0adf8256a42416584765625852b6e48497c90Mike Lockwood            if (isBlackListed(deviceName)) {
27646d0adf8256a42416584765625852b6e48497c90Mike Lockwood                throw new SecurityException("USB device is on a restricted bus");
27746d0adf8256a42416584765625852b6e48497c90Mike Lockwood            }
27846d0adf8256a42416584765625852b6e48497c90Mike Lockwood            UsbDevice device = mDevices.get(deviceName);
27946d0adf8256a42416584765625852b6e48497c90Mike Lockwood            if (device == null) {
28046d0adf8256a42416584765625852b6e48497c90Mike Lockwood                // if it is not in mDevices, it either does not exist or is blacklisted
28146d0adf8256a42416584765625852b6e48497c90Mike Lockwood                throw new IllegalArgumentException(
28246d0adf8256a42416584765625852b6e48497c90Mike Lockwood                        "device " + deviceName + " does not exist or is restricted");
28346d0adf8256a42416584765625852b6e48497c90Mike Lockwood            }
284fc3f24b4b60c10e0d3f41f70df37e11ea311cc2cJeff Sharkey            getCurrentSettings().checkPermission(device);
28546d0adf8256a42416584765625852b6e48497c90Mike Lockwood            return nativeOpenDevice(deviceName);
28646d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
28746d0adf8256a42416584765625852b6e48497c90Mike Lockwood    }
28846d0adf8256a42416584765625852b6e48497c90Mike Lockwood
2892dbccc1926ea2d3e27c5cfd2d61d2b3d5ed787c0Jeff Brown    public void dump(IndentingPrintWriter pw) {
29046d0adf8256a42416584765625852b6e48497c90Mike Lockwood        synchronized (mLock) {
2912dbccc1926ea2d3e27c5cfd2d61d2b3d5ed787c0Jeff Brown            pw.println("USB Host State:");
29246d0adf8256a42416584765625852b6e48497c90Mike Lockwood            for (String name : mDevices.keySet()) {
2932dbccc1926ea2d3e27c5cfd2d61d2b3d5ed787c0Jeff Brown                pw.println("  " + name + ": " + mDevices.get(name));
29446d0adf8256a42416584765625852b6e48497c90Mike Lockwood            }
29546d0adf8256a42416584765625852b6e48497c90Mike Lockwood        }
29646d0adf8256a42416584765625852b6e48497c90Mike Lockwood    }
29746d0adf8256a42416584765625852b6e48497c90Mike Lockwood
29846d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private native void monitorUsbHostBus();
29946d0adf8256a42416584765625852b6e48497c90Mike Lockwood    private native ParcelFileDescriptor nativeOpenDevice(String deviceName);
30046d0adf8256a42416584765625852b6e48497c90Mike Lockwood}
301