diff options
6 files changed, 98 insertions, 190 deletions
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl index c79a4583f8a8..495fa21a0360 100644 --- a/core/java/android/hardware/usb/IUsbManager.aidl +++ b/core/java/android/hardware/usb/IUsbManager.aidl @@ -77,8 +77,8 @@ interface IUsbManager void grantAccessoryPermission(in UsbAccessory accessory, int uid); /* Returns true if the USB manager has default preferences or permissions for the package */ - boolean hasDefaults(String packageName, int uid); + boolean hasDefaults(String packageName); /* Clears default preferences and permissions for the package */ - oneway void clearDefaults(String packageName, int uid); + oneway void clearDefaults(String packageName); } diff --git a/core/java/android/hardware/usb/UsbAccessory.java b/core/java/android/hardware/usb/UsbAccessory.java index 6cd9178ffead..7d66caafbd04 100644 --- a/core/java/android/hardware/usb/UsbAccessory.java +++ b/core/java/android/hardware/usb/UsbAccessory.java @@ -109,6 +109,14 @@ public class UsbAccessory implements Parcelable { } @Override + public int hashCode() { + return ((mManufacturer == null ? 0 : mManufacturer.hashCode()) ^ + (mModel == null ? 0 : mModel.hashCode()) ^ + (mType == null ? 0 : mType.hashCode()) ^ + (mVersion == null ? 0 : mVersion.hashCode())); + } + + @Override public String toString() { return "UsbAccessory[mManufacturer=" + mManufacturer + ", mModel=" + mModel + diff --git a/core/java/android/hardware/usb/UsbDevice.java b/core/java/android/hardware/usb/UsbDevice.java index 37bd82b851b9..39254b3851f4 100644 --- a/core/java/android/hardware/usb/UsbDevice.java +++ b/core/java/android/hardware/usb/UsbDevice.java @@ -270,6 +270,11 @@ public final class UsbDevice implements Parcelable { } @Override + public int hashCode() { + return mName.hashCode(); + } + + @Override public String toString() { return "UsbDevice[mName=" + mName + ",mVendorId=" + mVendorId + ",mProductId=" + mProductId + ",mClass=" + mClass + diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index 9f1b8eaab2d7..5df0ac7f4c0f 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -281,6 +281,9 @@ public class UsbManager { /** * Returns true if the caller has permission to access the device. + * Permission might have been granted temporarily via + * {@link #requestPermission(android.hardware.usb.UsbDevice} or + * by the user choosing the caller as the default application for the device. * * @param device to check permissions for * @return true if caller has permission @@ -296,6 +299,9 @@ public class UsbManager { /** * Returns true if the caller has permission to access the accessory. + * Permission might have been granted temporarily via + * {@link #requestPermission(android.hardware.usb.UsbAccessory} or + * by the user choosing the caller as the default application for the accessory. * * @param accessory to check permissions for * @return true if caller has permission @@ -310,10 +316,13 @@ public class UsbManager { } /** - * Requests permission for the given package to access the device. + * Requests temporary permission for the given package to access the device. * This may result in a system dialog being displayed to the user * if permission had not already been granted. * Success or failure is returned via the {@link android.app.PendingIntent} pi. + * If successful, this grants the caller permission to access the device only + * until the device is disconnected. + * * The following extras will be added to pi: * <ul> * <li> {@link #EXTRA_DEVICE} containing the device passed into this call @@ -333,10 +342,13 @@ public class UsbManager { } /** - * Requests permission for the given package to access the accessory. + * Requests temporary permission for the given package to access the accessory. * This may result in a system dialog being displayed to the user * if permission had not already been granted. * Success or failure is returned via the {@link android.app.PendingIntent} pi. + * If successful, this grants the caller permission to access the device only + * until the device is disconnected. + * * The following extras will be added to pi: * <ul> * <li> {@link #EXTRA_ACCESSORY} containing the accessory passed into this call diff --git a/services/java/com/android/server/usb/UsbDeviceSettingsManager.java b/services/java/com/android/server/usb/UsbDeviceSettingsManager.java index 29e6f94d5971..25eac6f5ebf7 100644 --- a/services/java/com/android/server/usb/UsbDeviceSettingsManager.java +++ b/services/java/com/android/server/usb/UsbDeviceSettingsManager.java @@ -35,7 +35,7 @@ import android.os.Binder; import android.os.FileUtils; import android.os.Process; import android.util.Log; -import android.util.SparseArray; +import android.util.SparseBooleanArray; import android.util.Xml; import com.android.internal.content.PackageMonitor; @@ -65,16 +65,16 @@ class UsbDeviceSettingsManager { private final Context mContext; - // maps UID to user approved USB devices - private final SparseArray<ArrayList<DeviceFilter>> mDevicePermissionMap = - new SparseArray<ArrayList<DeviceFilter>>(); - // maps UID to user approved USB accessories - private final SparseArray<ArrayList<AccessoryFilter>> mAccessoryPermissionMap = - new SparseArray<ArrayList<AccessoryFilter>>(); + // Temporary mapping USB device name to list of UIDs with permissions for the device + private final HashMap<String, SparseBooleanArray> mDevicePermissionMap = + new HashMap<String, SparseBooleanArray>(); + // Temporary mapping UsbAccessory to list of UIDs with permissions for the accessory + private final HashMap<UsbAccessory, SparseBooleanArray> mAccessoryPermissionMap = + new HashMap<UsbAccessory, SparseBooleanArray>(); // Maps DeviceFilter to user preferred application package private final HashMap<DeviceFilter, String> mDevicePreferenceMap = new HashMap<DeviceFilter, String>(); - // Maps DeviceFilter to user preferred application package + // Maps AccessoryFilter to user preferred application package private final HashMap<AccessoryFilter, String> mAccessoryPreferenceMap = new HashMap<AccessoryFilter, String>(); @@ -354,15 +354,6 @@ class UsbDeviceSettingsManager { } } } - - public void onUidRemoved(int uid) { - synchronized (mLock) { - // clear all permissions for the UID - if (clearUidDefaultsLocked(uid)) { - writeSettingsLocked(); - } - } - } } MyPackageMonitor mPackageMonitor = new MyPackageMonitor(); @@ -374,44 +365,6 @@ class UsbDeviceSettingsManager { mPackageMonitor.register(context, true); } - private void readDevicePermission(XmlPullParser parser) - throws XmlPullParserException, IOException { - int uid = -1; - ArrayList<DeviceFilter> filters = new ArrayList<DeviceFilter>(); - int count = parser.getAttributeCount(); - for (int i = 0; i < count; i++) { - if ("uid".equals(parser.getAttributeName(i))) { - uid = Integer.parseInt(parser.getAttributeValue(i)); - break; - } - } - XmlUtils.nextElement(parser); - while ("usb-device".equals(parser.getName())) { - filters.add(DeviceFilter.read(parser)); - XmlUtils.nextElement(parser); - } - mDevicePermissionMap.put(uid, filters); - } - - private void readAccessoryPermission(XmlPullParser parser) - throws XmlPullParserException, IOException { - int uid = -1; - ArrayList<AccessoryFilter> filters = new ArrayList<AccessoryFilter>(); - int count = parser.getAttributeCount(); - for (int i = 0; i < count; i++) { - if ("uid".equals(parser.getAttributeName(i))) { - uid = Integer.parseInt(parser.getAttributeValue(i)); - break; - } - } - XmlUtils.nextElement(parser); - while ("usb-accessory".equals(parser.getName())) { - filters.add(AccessoryFilter.read(parser)); - XmlUtils.nextElement(parser); - } - mAccessoryPermissionMap.put(uid, filters); - } - private void readPreference(XmlPullParser parser) throws XmlPullParserException, IOException { String packageName = null; @@ -443,11 +396,7 @@ class UsbDeviceSettingsManager { XmlUtils.nextElement(parser); while (parser.getEventType() != XmlPullParser.END_DOCUMENT) { String tagName = parser.getName(); - if ("device-permission".equals(tagName)) { - readDevicePermission(parser); - } else if ("accessory-permission".equals(tagName)) { - readAccessoryPermission(parser); - } else if ("preference".equals(tagName)) { + if ("preference".equals(tagName)) { readPreference(parser); } else { XmlUtils.nextElement(parser); @@ -480,32 +429,6 @@ class UsbDeviceSettingsManager { serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); serializer.startTag(null, "settings"); - int count = mDevicePermissionMap.size(); - for (int i = 0; i < count; i++) { - int uid = mDevicePermissionMap.keyAt(i); - ArrayList<DeviceFilter> filters = mDevicePermissionMap.valueAt(i); - serializer.startTag(null, "device-permission"); - serializer.attribute(null, "uid", Integer.toString(uid)); - int filterCount = filters.size(); - for (int j = 0; j < filterCount; j++) { - filters.get(j).write(serializer); - } - serializer.endTag(null, "device-permission"); - } - - count = mAccessoryPermissionMap.size(); - for (int i = 0; i < count; i++) { - int uid = mAccessoryPermissionMap.keyAt(i); - ArrayList<AccessoryFilter> filters = mAccessoryPermissionMap.valueAt(i); - serializer.startTag(null, "accessory-permission"); - serializer.attribute(null, "uid", Integer.toString(uid)); - int filterCount = filters.size(); - for (int j = 0; j < filterCount; j++) { - filters.get(j).write(serializer); - } - serializer.endTag(null, "accessory-permission"); - } - for (DeviceFilter filter : mDevicePreferenceMap.keySet()) { serializer.startTag(null, "preference"); serializer.attribute(null, "package", mDevicePreferenceMap.get(filter)); @@ -621,6 +544,9 @@ class UsbDeviceSettingsManager { } public void deviceDetached(UsbDevice device) { + // clear temporary permissions for the device + mDevicePermissionMap.remove(device.getDeviceName()); + Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED); intent.putExtra(UsbManager.EXTRA_DEVICE, device); Log.d(TAG, "usbDeviceRemoved, sending " + intent); @@ -644,6 +570,16 @@ class UsbDeviceSettingsManager { resolveActivity(intent, matches, defaultPackage, null, accessory); } + public void accessoryDetached(UsbAccessory accessory) { + // clear temporary permissions for the accessory + mAccessoryPermissionMap.remove(accessory); + + Intent intent = new Intent( + UsbManager.ACTION_USB_ACCESSORY_DETACHED); + intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); + mContext.sendBroadcast(intent); + } + private void resolveActivity(Intent intent, ArrayList<ResolveInfo> matches, String defaultPackage, UsbDevice device, UsbAccessory accessory) { int count = matches.size(); @@ -659,13 +595,6 @@ class UsbDeviceSettingsManager { rInfo.activityInfo.applicationInfo != null && (rInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { defaultRI = rInfo; - int uid = rInfo.activityInfo.applicationInfo.uid; - // grant permission - if (device != null) { - grantDevicePermission(device, uid); - } else if (accessory != null) { - grantAccessoryPermission(accessory, uid); - } } } @@ -682,6 +611,13 @@ class UsbDeviceSettingsManager { } if (defaultRI != null) { + // grant permission for default activity + if (device != null) { + grantDevicePermission(device, defaultRI.activityInfo.applicationInfo.uid); + } else if (accessory != null) { + grantAccessoryPermission(accessory, defaultRI.activityInfo.applicationInfo.uid); + } + // start default activity directly try { intent.setComponent( @@ -711,47 +647,24 @@ class UsbDeviceSettingsManager { } } - public void accessoryDetached(UsbAccessory accessory) { - Intent intent = new Intent( - UsbManager.ACTION_USB_ACCESSORY_DETACHED); - intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); - mContext.sendBroadcast(intent); - } - public boolean hasPermission(UsbDevice device) { synchronized (mLock) { - ArrayList<DeviceFilter> filterList = - mDevicePermissionMap.get(Binder.getCallingUid()); - if (filterList != null) { - int count = filterList.size(); - for (int i = 0; i < count; i++) { - DeviceFilter filter = filterList.get(i); - if (filter.equals(device)) { - // permission allowed - return true; - } - } + SparseBooleanArray uidList = mDevicePermissionMap.get(device.getDeviceName()); + if (uidList == null) { + return false; } + return uidList.get(Binder.getCallingUid()); } - return false; } public boolean hasPermission(UsbAccessory accessory) { synchronized (mLock) { - ArrayList<AccessoryFilter> filterList = - mAccessoryPermissionMap.get(Binder.getCallingUid()); - if (filterList != null) { - int count = filterList.size(); - for (int i = 0; i < count; i++) { - AccessoryFilter filter = filterList.get(i); - if (filter.equals(accessory)) { - // permission allowed - return true; - } - } + SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory); + if (uidList == null) { + return false; } + return uidList.get(Binder.getCallingUid()); } - return false; } public void checkPermission(UsbDevice device) { @@ -873,73 +786,43 @@ class UsbDeviceSettingsManager { public void grantDevicePermission(UsbDevice device, int uid) { synchronized (mLock) { - ArrayList<DeviceFilter> filterList = mDevicePermissionMap.get(uid); - if (filterList == null) { - filterList = new ArrayList<DeviceFilter>(); - mDevicePermissionMap.put(uid, filterList); - } else { - int count = filterList.size(); - for (int i = 0; i < count; i++) { - if (filterList.get(i).equals(device)) return; - } + String deviceName = device.getDeviceName(); + SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName); + if (uidList == null) { + uidList = new SparseBooleanArray(1); + mDevicePermissionMap.put(deviceName, uidList); } - filterList.add(new DeviceFilter(device)); - writeSettingsLocked(); + uidList.put(uid, true); } } public void grantAccessoryPermission(UsbAccessory accessory, int uid) { synchronized (mLock) { - ArrayList<AccessoryFilter> filterList = mAccessoryPermissionMap.get(uid); - if (filterList == null) { - filterList = new ArrayList<AccessoryFilter>(); - mAccessoryPermissionMap.put(uid, filterList); - } else { - int count = filterList.size(); - for (int i = 0; i < count; i++) { - if (filterList.get(i).equals(accessory)) return; - } + SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory); + if (uidList == null) { + uidList = new SparseBooleanArray(1); + mAccessoryPermissionMap.put(accessory, uidList); } - filterList.add(new AccessoryFilter(accessory)); - writeSettingsLocked(); + uidList.put(uid, true); } } - public boolean hasDefaults(String packageName, int uid) { + public boolean hasDefaults(String packageName) { synchronized (mLock) { - if (mDevicePermissionMap.get(uid) != null) return true; - if (mAccessoryPermissionMap.get(uid) != null) return true; if (mDevicePreferenceMap.values().contains(packageName)) return true; if (mAccessoryPreferenceMap.values().contains(packageName)) return true; return false; } } - public void clearDefaults(String packageName, int uid) { + public void clearDefaults(String packageName) { synchronized (mLock) { - boolean packageCleared = clearPackageDefaultsLocked(packageName); - boolean uidCleared = clearUidDefaultsLocked(uid); - if (packageCleared || uidCleared) { + if (clearPackageDefaultsLocked(packageName)) { writeSettingsLocked(); } } } - private boolean clearUidDefaultsLocked(int uid) { - boolean cleared = false; - int index = mDevicePermissionMap.indexOfKey(uid); - if (index >= 0) { - mDevicePermissionMap.removeAt(index); - cleared = true; - } - index = mAccessoryPermissionMap.indexOfKey(uid); - if (index >= 0) { - mAccessoryPermissionMap.removeAt(index); - cleared = true; - } - return cleared; - } - private boolean clearPackageDefaultsLocked(String packageName) { boolean cleared = false; synchronized (mLock) { @@ -972,24 +855,24 @@ class UsbDeviceSettingsManager { public void dump(FileDescriptor fd, PrintWriter pw) { synchronized (mLock) { pw.println(" Device permissions:"); - int count = mDevicePermissionMap.size(); - for (int i = 0; i < count; i++) { - int uid = mDevicePermissionMap.keyAt(i); - pw.println(" " + "uid " + uid + ":"); - ArrayList<DeviceFilter> filters = mDevicePermissionMap.valueAt(i); - for (DeviceFilter filter : filters) { - pw.println(" " + filter); + for (String deviceName : mDevicePermissionMap.keySet()) { + pw.print(" " + deviceName + ": "); + SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName); + int count = uidList.size(); + for (int i = 0; i < count; i++) { + pw.print(Integer.toString(uidList.keyAt(i)) + " "); } + pw.println(""); } pw.println(" Accessory permissions:"); - count = mAccessoryPermissionMap.size(); - for (int i = 0; i < count; i++) { - int uid = mAccessoryPermissionMap.keyAt(i); - pw.println(" " + "uid " + uid + ":"); - ArrayList<AccessoryFilter> filters = mAccessoryPermissionMap.valueAt(i); - for (AccessoryFilter filter : filters) { - pw.println(" " + filter); + for (UsbAccessory accessory : mAccessoryPermissionMap.keySet()) { + pw.print(" " + accessory + ": "); + SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory); + int count = uidList.size(); + for (int i = 0; i < count; i++) { + pw.print(Integer.toString(uidList.keyAt(i)) + " "); } + pw.println(""); } pw.println(" Device preferences:"); for (DeviceFilter filter : mDevicePreferenceMap.keySet()) { diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java index d0a24920943b..71f2a9b04782 100644 --- a/services/java/com/android/server/usb/UsbService.java +++ b/services/java/com/android/server/usb/UsbService.java @@ -483,14 +483,14 @@ public class UsbService extends IUsbManager.Stub { mDeviceManager.grantAccessoryPermission(accessory, uid); } - public boolean hasDefaults(String packageName, int uid) { + public boolean hasDefaults(String packageName) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); - return mDeviceManager.hasDefaults(packageName, uid); + return mDeviceManager.hasDefaults(packageName); } - public void clearDefaults(String packageName, int uid) { + public void clearDefaults(String packageName) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); - mDeviceManager.clearDefaults(packageName, uid); + mDeviceManager.clearDefaults(packageName); } /* |