diff options
| -rw-r--r-- | api/current.xml | 13 | ||||
| -rw-r--r-- | core/java/android/hardware/UsbConstants.java | 5 | ||||
| -rw-r--r-- | core/res/res/values/config.xml | 8 | ||||
| -rw-r--r-- | services/java/com/android/server/UsbService.java | 50 |
4 files changed, 65 insertions, 11 deletions
diff --git a/api/current.xml b/api/current.xml index 4a4a355c0bfa..8366600d7a50 100644 --- a/api/current.xml +++ b/api/current.xml @@ -94408,6 +94408,17 @@ visibility="public" > </field> +<field name="USB_INTERFACE_SUBCLASS_BOOT" + type="int" + transient="false" + volatile="false" + value="1" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="USB_SUBCLASS_VENDOR_SPEC" type="int" transient="false" @@ -263792,7 +263803,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="arg0" type="T"> +<parameter name="t" type="T"> </parameter> </method> </interface> diff --git a/core/java/android/hardware/UsbConstants.java b/core/java/android/hardware/UsbConstants.java index 29a335cdbed8..4c8c4d4db9dc 100644 --- a/core/java/android/hardware/UsbConstants.java +++ b/core/java/android/hardware/UsbConstants.java @@ -41,6 +41,7 @@ public final class UsbConstants { public static final int USB_ENDPOINT_XFER_BULK = 2; public static final int USB_ENDPOINT_XFER_INT = 3; + // USB classes public static final int USB_CLASS_PER_INTERFACE = 0; public static final int USB_CLASS_AUDIO = 1; public static final int USB_CLASS_COMM = 2; @@ -58,6 +59,8 @@ public final class UsbConstants { public static final int USB_CLASS_MISC = 0xef; public static final int USB_CLASS_APP_SPEC = 0xfe; public static final int USB_CLASS_VENDOR_SPEC = 0xff; - public static final int USB_SUBCLASS_VENDOR_SPEC = 0xff; + // USB subclasses + public static final int USB_INTERFACE_SUBCLASS_BOOT = 1; // for HID class + public static final int USB_SUBCLASS_VENDOR_SPEC = 0xff; }
\ No newline at end of file diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 713fa8e96284..0edd33e35c86 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -284,6 +284,14 @@ <!-- Indicate whether the device has USB host support. --> <bool name="config_hasUsbHostSupport">false</bool> + <!-- List of file paths for USB host busses to exclude from USB host support. + For example, if the first USB bus on the device is used to communicate + with the modem or some other restricted hardware, add "/dev/bus/usb/001/" + to this list. If this is empty, no parts of the host USB bus will be excluded. + --> + <string-array name="config_usbHostBlacklist"> + </string-array> + <!-- Vibrator pattern for feedback about a long screen/key press --> <integer-array name="config_longPressVibePattern"> <item>0</item> diff --git a/services/java/com/android/server/UsbService.java b/services/java/com/android/server/UsbService.java index 5c03fb2a76e4..460fd4d5eb7c 100644 --- a/services/java/com/android/server/UsbService.java +++ b/services/java/com/android/server/UsbService.java @@ -83,6 +83,9 @@ class UsbService extends IUsbManager.Stub { private final HashMap<String,UsbDevice> mDevices = new HashMap<String,UsbDevice>(); + // USB busses to exclude from USB host support + private final String[] mHostBlacklist; + private boolean mSystemReady; private final Context mContext; @@ -143,6 +146,9 @@ class UsbService extends IUsbManager.Stub { public UsbService(Context context) { mContext = context; + mHostBlacklist = context.getResources().getStringArray( + com.android.internal.R.array.config_usbHostBlacklist); + init(); // set initial status if (mConfiguration >= 0) { @@ -197,6 +203,29 @@ class UsbService extends IUsbManager.Stub { } } + private boolean isBlackListed(String deviceName) { + int count = mHostBlacklist.length; + for (int i = 0; i < count; i++) { + if (deviceName.startsWith(mHostBlacklist[i])) { + return true; + } + } + return false; + } + + private boolean isBlackListed(int clazz, int subClass, int protocol) { + // blacklist hubs + if (clazz == UsbConstants.USB_CLASS_HUB) return true; + + // blacklist HID boot devices (mouse and keyboard) + if (clazz == UsbConstants.USB_CLASS_HID && + subClass == UsbConstants.USB_INTERFACE_SUBCLASS_BOOT) { + return true; + } + + return false; + } + // called from JNI in monitorUsbHostBus() private void usbDeviceAdded(String deviceName, int vendorID, int productID, int deviceClass, int deviceSubclass, int deviceProtocol, @@ -207,8 +236,8 @@ class UsbService extends IUsbManager.Stub { and interval for each endpoint */ int[] endpointValues) { - // ignore hubs - if (deviceClass == UsbConstants.USB_CLASS_HUB) { + if (isBlackListed(deviceName) || + isBlackListed(deviceClass, deviceSubclass, deviceProtocol)) { return; } @@ -223,7 +252,6 @@ class UsbService extends IUsbManager.Stub { try { // repackage interfaceValues as an array of UsbInterface int intf, endp, ival = 0, eval = 0; - boolean hasGoodInterface = false; for (intf = 0; intf < numInterfaces; intf++) { int interfaceId = interfaceValues[ival++]; int interfaceClass = interfaceValues[ival++]; @@ -241,16 +269,13 @@ class UsbService extends IUsbManager.Stub { maxPacketSize, interval); } - if (interfaceClass != UsbConstants.USB_CLASS_HUB) { - hasGoodInterface = true; + // don't allow if any interfaces are blacklisted + if (isBlackListed(interfaceClass, interfaceSubclass, interfaceProtocol)) { + return; } interfaces[intf] = new UsbInterface(interfaceId, interfaceClass, interfaceSubclass, interfaceProtocol, endpoints); } - - if (!hasGoodInterface) { - return; - } } catch (Exception e) { // beware of index out of bound exceptions, which might happen if // a device does not set bNumEndpoints correctly @@ -328,7 +353,14 @@ class UsbService extends IUsbManager.Stub { } public ParcelFileDescriptor openDevice(String deviceName) { + if (isBlackListed(deviceName)) { + throw new SecurityException("USB device is on a restricted bus"); + } mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_USB, null); + if (mDevices.get(deviceName) == null) { + // if it is not in mDevices, it either does not exist or is blacklisted + throw new IllegalArgumentException("device " + deviceName + " does not exist or is restricted"); + } return nativeOpenDevice(deviceName); } |