diff options
author | Evan Severson <evanseverson@google.com> | 2019-08-23 16:51:16 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2019-08-23 16:51:16 +0000 |
commit | 9727c0581a456a6ea18c7858d69b9f2de18af9f4 (patch) | |
tree | 7292e165f057b4e41ed3b6883dad2381961ed479 /services/usb/java | |
parent | 903102c43014cccea9d0365a0700bd617faf2453 (diff) | |
parent | e05005b18f87215f0d9274a12dae6fde9ad8a23d (diff) |
Merge "Separate Usb permissions from Usb settings"
Diffstat (limited to 'services/usb/java')
9 files changed, 532 insertions, 480 deletions
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index 7f7a78bd1d17..9f3b07b951be 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -250,7 +250,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser } public UsbDeviceManager(Context context, UsbAlsaManager alsaManager, - UsbSettingsManager settingsManager) { + UsbSettingsManager settingsManager, UsbPermissionManager permissionManager) { mContext = context; mContentResolver = context.getContentResolver(); PackageManager pm = mContext.getPackageManager(); @@ -284,13 +284,13 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser * Initialze the legacy UsbHandler */ mHandler = new UsbHandlerLegacy(FgThread.get().getLooper(), mContext, this, - alsaManager, settingsManager); + alsaManager, permissionManager); } else { /** * Initialize HAL based UsbHandler */ mHandler = new UsbHandlerHal(FgThread.get().getLooper(), mContext, this, - alsaManager, settingsManager); + alsaManager, permissionManager); } if (nativeIsStartRequested()) { @@ -468,7 +468,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser private final Context mContext; private final UsbAlsaManager mUsbAlsaManager; - private final UsbSettingsManager mSettingsManager; + private final UsbPermissionManager mPermissionManager; private NotificationManager mNotificationManager; protected long mScreenUnlockedFunctions; @@ -489,12 +489,12 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser protected static final String USB_PERSISTENT_CONFIG_PROPERTY = "persist.sys.usb.config"; UsbHandler(Looper looper, Context context, UsbDeviceManager deviceManager, - UsbAlsaManager alsaManager, UsbSettingsManager settingsManager) { + UsbAlsaManager alsaManager, UsbPermissionManager permissionManager) { super(looper); mContext = context; mUsbDeviceManager = deviceManager; mUsbAlsaManager = alsaManager; - mSettingsManager = settingsManager; + mPermissionManager = permissionManager; mContentResolver = context.getContentResolver(); mCurrentUser = ActivityManager.getCurrentUser(); @@ -625,7 +625,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser // successfully entered accessory mode String[] accessoryStrings = mUsbDeviceManager.getAccessoryStrings(); if (accessoryStrings != null) { - UsbSerialReader serialReader = new UsbSerialReader(mContext, mSettingsManager, + UsbSerialReader serialReader = new UsbSerialReader(mContext, mPermissionManager, accessoryStrings[UsbAccessory.SERIAL_STRING]); mCurrentAccessory = new UsbAccessory( @@ -663,7 +663,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser if (mCurrentAccessory != null) { if (mBootCompleted) { - mSettingsManager.usbAccessoryRemoved(mCurrentAccessory); + mPermissionManager.usbAccessoryRemoved(mCurrentAccessory); } mCurrentAccessory = null; } @@ -1343,8 +1343,8 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser private boolean mUsbDataUnlocked; UsbHandlerLegacy(Looper looper, Context context, UsbDeviceManager deviceManager, - UsbAlsaManager alsaManager, UsbSettingsManager settingsManager) { - super(looper, context, deviceManager, alsaManager, settingsManager); + UsbAlsaManager alsaManager, UsbPermissionManager permissionManager) { + super(looper, context, deviceManager, alsaManager, permissionManager); try { readOemUsbOverrideConfig(context); // Restore default functions. @@ -1738,8 +1738,8 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser protected boolean mCurrentUsbFunctionsRequested; UsbHandlerHal(Looper looper, Context context, UsbDeviceManager deviceManager, - UsbAlsaManager alsaManager, UsbSettingsManager settingsManager) { - super(looper, context, deviceManager, alsaManager, settingsManager); + UsbAlsaManager alsaManager, UsbPermissionManager permissionManager) { + super(looper, context, deviceManager, alsaManager, permissionManager); try { ServiceNotification serviceNotification = new ServiceNotification(); @@ -1977,7 +1977,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser * @param uid Uid of the caller */ public ParcelFileDescriptor openAccessory(UsbAccessory accessory, - UsbUserSettingsManager settings, int uid) { + UsbUserPermissionManager permissions, int uid) { UsbAccessory currentAccessory = mHandler.getCurrentAccessory(); if (currentAccessory == null) { throw new IllegalArgumentException("no accessory attached"); @@ -1988,7 +1988,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser + currentAccessory; throw new IllegalArgumentException(error); } - settings.checkPermission(accessory, uid); + permissions.checkPermission(accessory, uid); return nativeOpenAccessory(); } diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java index 00c75480ba80..e899dff5e5a2 100644 --- a/services/usb/java/com/android/server/usb/UsbHostManager.java +++ b/services/usb/java/com/android/server/usb/UsbHostManager.java @@ -65,7 +65,7 @@ public class UsbHostManager { private final String[] mHostBlacklist; private final UsbAlsaManager mUsbAlsaManager; - private final UsbSettingsManager mSettingsManager; + private final UsbPermissionManager mPermissionManager; private final Object mLock = new Object(); @GuardedBy("mLock") @@ -232,13 +232,13 @@ public class UsbHostManager { * UsbHostManager */ public UsbHostManager(Context context, UsbAlsaManager alsaManager, - UsbSettingsManager settingsManager) { + UsbPermissionManager permissionManager) { mContext = context; mHostBlacklist = context.getResources().getStringArray( com.android.internal.R.array.config_usbHostBlacklist); mUsbAlsaManager = alsaManager; - mSettingsManager = settingsManager; + mPermissionManager = permissionManager; String deviceConnectionHandler = context.getResources().getString( com.android.internal.R.string.config_UsbDeviceConnectionHandling_component); if (!TextUtils.isEmpty(deviceConnectionHandler)) { @@ -393,8 +393,8 @@ public class UsbHostManager { addConnectionRecord(deviceAddress, ConnectionRecord.CONNECT_BADDEVICE, parser.getRawDescriptors()); } else { - UsbSerialReader serialNumberReader = new UsbSerialReader(mContext, mSettingsManager, - newDeviceBuilder.serialNumber); + UsbSerialReader serialNumberReader = new UsbSerialReader(mContext, + mPermissionManager, newDeviceBuilder.serialNumber); UsbDevice newDevice = newDeviceBuilder.build(serialNumberReader); serialNumberReader.setDevice(newDevice); @@ -444,7 +444,7 @@ public class UsbHostManager { if (device != null) { Slog.d(TAG, "Removed device at " + deviceAddress + ": " + device.getProductName()); mUsbAlsaManager.usbDeviceRemoved(deviceAddress); - mSettingsManager.usbDeviceRemoved(device); + mPermissionManager.usbDeviceRemoved(device); getCurrentUserSettings().usbDeviceRemoved(device); ConnectionRecord current = mConnected.get(deviceAddress); // Tracking @@ -484,9 +484,11 @@ public class UsbHostManager { } } - /* Opens the specified USB device */ - public ParcelFileDescriptor openDevice(String deviceAddress, UsbUserSettingsManager settings, - String packageName, int uid) { + /** + * Opens the specified USB device + */ + public ParcelFileDescriptor openDevice(String deviceAddress, + UsbUserPermissionManager permissions, String packageName, int uid) { synchronized (mLock) { if (isBlackListed(deviceAddress)) { throw new SecurityException("USB device is on a restricted bus"); @@ -498,7 +500,7 @@ public class UsbHostManager { "device " + deviceAddress + " does not exist or is restricted"); } - settings.checkPermission(device, packageName, uid); + permissions.checkPermission(device, packageName, uid); return nativeOpenDevice(deviceAddress); } } diff --git a/services/usb/java/com/android/server/usb/UsbPermissionManager.java b/services/usb/java/com/android/server/usb/UsbPermissionManager.java index dd2f29ba74ae..14c7c7c8915e 100644 --- a/services/usb/java/com/android/server/usb/UsbPermissionManager.java +++ b/services/usb/java/com/android/server/usb/UsbPermissionManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright (C) 2019 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. @@ -17,230 +17,95 @@ package com.android.server.usb; import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.PendingIntent; -import android.content.ActivityNotFoundException; +import android.annotation.UserIdInt; import android.content.Context; import android.content.Intent; import android.hardware.usb.UsbAccessory; import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbManager; -import android.os.Binder; -import android.os.Process; import android.os.UserHandle; -import android.service.usb.UsbSettingsAccessoryPermissionProto; -import android.service.usb.UsbSettingsDevicePermissionProto; -import android.service.usb.UsbUserSettingsManagerProto; import android.util.Slog; -import android.util.SparseBooleanArray; +import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; -import com.android.internal.util.dump.DualDumpOutputStream; -import java.util.HashMap; - -/** - * UsbPermissionManager manages usb device or accessory access permissions. - * - * @hide - */ class UsbPermissionManager { private static final String LOG_TAG = UsbPermissionManager.class.getSimpleName(); + private static final boolean DEBUG = false; - @GuardedBy("mLock") - /** Temporary mapping USB device name to list of UIDs with permissions for the device*/ - private final HashMap<String, SparseBooleanArray> mDevicePermissionMap = - new HashMap<>(); - @GuardedBy("mLock") - /** Temporary mapping UsbAccessory to list of UIDs with permissions for the accessory*/ - private final HashMap<UsbAccessory, SparseBooleanArray> mAccessoryPermissionMap = - new HashMap<>(); + /** Context to be used by this module */ + private final @NonNull Context mContext; - private final UserHandle mUser; - private final boolean mDisablePermissionDialogs; + /** Map from user id to {@link UsbUserPermissionManager} for the user */ + @GuardedBy("mPermissionsByUser") + private final SparseArray<UsbUserPermissionManager> mPermissionsByUser = new SparseArray<>(); - private final Object mLock = new Object(); + final UsbService mUsbService; - UsbPermissionManager(@NonNull Context context, @NonNull UserHandle user) { - mUser = user; - mDisablePermissionDialogs = context.getResources().getBoolean( - com.android.internal.R.bool.config_disableUsbPermissionDialogs); + UsbPermissionManager(@NonNull Context context, + @NonNull UsbService usbService) { + mContext = context; + mUsbService = usbService; } - /** - * Removes access permissions of all packages for the USB accessory. - * - * @param accessory to remove permissions for - */ - void removeAccessoryPermissions(@NonNull UsbAccessory accessory) { - synchronized (mLock) { - mAccessoryPermissionMap.remove(accessory); + @NonNull UsbUserPermissionManager getPermissionsForUser(@UserIdInt int userId) { + synchronized (mPermissionsByUser) { + UsbUserPermissionManager permissions = mPermissionsByUser.get(userId); + if (permissions == null) { + permissions = new UsbUserPermissionManager(mContext, UserHandle.of(userId), + mUsbService.getSettingsForUser(userId)); + mPermissionsByUser.put(userId, permissions); + } + return permissions; } } - /** - * Removes access permissions of all packages for the USB device. - * - * @param device to remove permissions for - */ - void removeDevicePermissions(@NonNull UsbDevice device) { - synchronized (mLock) { - mDevicePermissionMap.remove(device.getDeviceName()); + void remove(@NonNull UserHandle userToRemove) { + synchronized (mPermissionsByUser) { + mPermissionsByUser.remove(userToRemove.getIdentifier()); } } /** - * Grants permission for USB device without showing system dialog for package with uid. + * Remove temporary access permission and broadcast that a device was removed. * - * @param device to grant permission for - * @param uid to grant permission for + * @param device The device that is removed */ - void grantDevicePermission(@NonNull UsbDevice device, int uid) { - synchronized (mLock) { - String deviceName = device.getDeviceName(); - SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName); - if (uidList == null) { - uidList = new SparseBooleanArray(1); - mDevicePermissionMap.put(deviceName, uidList); + void usbDeviceRemoved(@NonNull UsbDevice device) { + synchronized (mPermissionsByUser) { + for (int i = 0; i < mPermissionsByUser.size(); i++) { + // clear temporary permissions for the device + mPermissionsByUser.valueAt(i).removeDevicePermissions(device); } - uidList.put(uid, true); } - } - /** - * Grants permission for USB accessory without showing system dialog for package with uid. - * - * @param accessory to grant permission for - * @param uid to grant permission for - */ - void grantAccessoryPermission(@NonNull UsbAccessory accessory, int uid) { - synchronized (mLock) { - SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory); - if (uidList == null) { - uidList = new SparseBooleanArray(1); - mAccessoryPermissionMap.put(accessory, uidList); - } - uidList.put(uid, true); - } - } + Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED); + intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); + intent.putExtra(UsbManager.EXTRA_DEVICE, device); - /** - * Returns true if package with uid has permission to access the device. - * - * @param device to check permission for - * @param uid to check permission for - * @return {@code true} if package with uid has permission - */ - boolean hasPermission(@NonNull UsbDevice device, int uid) { - synchronized (mLock) { - if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) { - return true; - } - SparseBooleanArray uidList = mDevicePermissionMap.get(device.getDeviceName()); - if (uidList == null) { - return false; - } - return uidList.get(uid); + if (DEBUG) { + Slog.d(LOG_TAG, "usbDeviceRemoved, sending " + intent); } + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } /** - * Returns true if caller has permission to access the accessory. + * Remove temporary access permission and broadcast that a accessory was removed. * - * @param accessory to check permission for - * @param uid to check permission for - * @return {@code true} if caller has permssion + * @param accessory The accessory that is removed */ - boolean hasPermission(@NonNull UsbAccessory accessory, int uid) { - synchronized (mLock) { - if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) { - return true; - } - SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory); - if (uidList == null) { - return false; + void usbAccessoryRemoved(@NonNull UsbAccessory accessory) { + synchronized (mPermissionsByUser) { + for (int i = 0; i < mPermissionsByUser.size(); i++) { + // clear temporary permissions for the accessory + mPermissionsByUser.valueAt(i).removeAccessoryPermissions(accessory); } - return uidList.get(uid); } - } - /** - * Creates UI dialog to request permission for the given package to access the device - * or accessory. - * - * @param device The USB device attached - * @param accessory The USB accessory attached - * @param canBeDefault Whether the calling pacakge can set as default handler - * of the USB device or accessory - * @param packageName The package name of the calling package - * @param uid The uid of the calling package - * @param userContext The context to start the UI dialog - * @param pi PendingIntent for returning result - */ - void requestPermissionDialog(@Nullable UsbDevice device, - @Nullable UsbAccessory accessory, - boolean canBeDefault, - @NonNull String packageName, - int uid, - @NonNull Context userContext, - @NonNull PendingIntent pi) { - long identity = Binder.clearCallingIdentity(); - Intent intent = new Intent(); - if (device != null) { - intent.putExtra(UsbManager.EXTRA_DEVICE, device); - } else { - intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); - } - intent.putExtra(Intent.EXTRA_INTENT, pi); - intent.putExtra(Intent.EXTRA_UID, uid); - intent.putExtra(UsbManager.EXTRA_CAN_BE_DEFAULT, canBeDefault); - intent.putExtra(UsbManager.EXTRA_PACKAGE, packageName); - intent.setClassName("com.android.systemui", - "com.android.systemui.usb.UsbPermissionActivity"); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - - try { - userContext.startActivityAsUser(intent, mUser); - } catch (ActivityNotFoundException e) { - Slog.e(LOG_TAG, "unable to start UsbPermissionActivity"); - } finally { - Binder.restoreCallingIdentity(identity); - } + Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_DETACHED); + intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); + intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } - void dump(@NonNull DualDumpOutputStream dump) { - synchronized (mLock) { - for (String deviceName : mDevicePermissionMap.keySet()) { - long devicePermissionToken = dump.start("device_permissions", - UsbUserSettingsManagerProto.DEVICE_PERMISSIONS); - - dump.write("device_name", UsbSettingsDevicePermissionProto.DEVICE_NAME, deviceName); - - SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName); - int count = uidList.size(); - for (int i = 0; i < count; i++) { - dump.write("uids", UsbSettingsDevicePermissionProto.UIDS, uidList.keyAt(i)); - } - - dump.end(devicePermissionToken); - } - - for (UsbAccessory accessory : mAccessoryPermissionMap.keySet()) { - long accessoryPermissionToken = dump.start("accessory_permissions", - UsbUserSettingsManagerProto.ACCESSORY_PERMISSIONS); - - dump.write("accessory_description", - UsbSettingsAccessoryPermissionProto.ACCESSORY_DESCRIPTION, - accessory.getDescription()); - - SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory); - int count = uidList.size(); - for (int i = 0; i < count; i++) { - dump.write("uids", UsbSettingsAccessoryPermissionProto.UIDS, uidList.keyAt(i)); - } - - dump.end(accessoryPermissionToken); - } - } - } } diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java index 74c3939a1b1c..5e136bbf0694 100644 --- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java +++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java @@ -783,7 +783,7 @@ class UsbProfileGroupSettingsManager { return; } - mSettingsManager.getSettingsForUser(UserHandle.getUserId(appInfo.uid)) + mSettingsManager.mUsbService.getPermissionsForUser(UserHandle.getUserId(appInfo.uid)) .grantDevicePermission(device, appInfo.uid); Intent activityIntent = new Intent(intent); @@ -844,14 +844,15 @@ class UsbProfileGroupSettingsManager { } if (defaultActivity != null) { - UsbUserSettingsManager defaultRIUserSettings = mSettingsManager.getSettingsForUser( - UserHandle.getUserId(defaultActivity.applicationInfo.uid)); + UsbUserPermissionManager defaultRIUserPermissions = + mSettingsManager.mUsbService.getPermissionsForUser( + UserHandle.getUserId(defaultActivity.applicationInfo.uid)); // grant permission for default activity if (device != null) { - defaultRIUserSettings. - grantDevicePermission(device, defaultActivity.applicationInfo.uid); + defaultRIUserPermissions + .grantDevicePermission(device, defaultActivity.applicationInfo.uid); } else if (accessory != null) { - defaultRIUserSettings.grantAccessoryPermission(accessory, + defaultRIUserPermissions.grantAccessoryPermission(accessory, defaultActivity.applicationInfo.uid); } diff --git a/services/usb/java/com/android/server/usb/UsbSerialReader.java b/services/usb/java/com/android/server/usb/UsbSerialReader.java index 8ca77f0c63dc..3151679eb545 100644 --- a/services/usb/java/com/android/server/usb/UsbSerialReader.java +++ b/services/usb/java/com/android/server/usb/UsbSerialReader.java @@ -39,7 +39,7 @@ import com.android.internal.util.ArrayUtils; class UsbSerialReader extends IUsbSerialReader.Stub { private final @Nullable String mSerialNumber; private final @NonNull Context mContext; - private final @NonNull UsbSettingsManager mSettingsManager; + private final @NonNull UsbPermissionManager mPermissionManager; private Object mDevice; @@ -51,10 +51,10 @@ class UsbSerialReader extends IUsbSerialReader.Stub { * @param settingsManager The USB settings manager * @param serialNumber The serial number that might be read */ - UsbSerialReader(@NonNull Context context, @NonNull UsbSettingsManager settingsManager, + UsbSerialReader(@NonNull Context context, @NonNull UsbPermissionManager permissionManager, @Nullable String serialNumber) { mContext = context; - mSettingsManager = settingsManager; + mPermissionManager = permissionManager; mSerialNumber = serialNumber; } @@ -89,13 +89,14 @@ class UsbSerialReader extends IUsbSerialReader.Stub { if (packageTargetSdkVersion >= Build.VERSION_CODES.Q) { if (mContext.checkPermission(android.Manifest.permission.MANAGE_USB, pid, uid) == PackageManager.PERMISSION_DENIED) { - UsbUserSettingsManager settings = mSettingsManager.getSettingsForUser( - UserHandle.getUserId(uid)); + int userId = UserHandle.getUserId(uid); if (mDevice instanceof UsbDevice) { - settings.checkPermission((UsbDevice) mDevice, packageName, uid); + mPermissionManager.getPermissionsForUser(userId) + .checkPermission((UsbDevice) mDevice, packageName, uid); } else { - settings.checkPermission((UsbAccessory) mDevice, uid); + mPermissionManager.getPermissionsForUser(userId) + .checkPermission((UsbAccessory) mDevice, uid); } } } diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java index 4be68b83dbcb..cc1490e09ef6 100644 --- a/services/usb/java/com/android/server/usb/UsbService.java +++ b/services/usb/java/com/android/server/usb/UsbService.java @@ -121,6 +121,7 @@ public class UsbService extends IUsbManager.Stub { private final UsbAlsaManager mAlsaManager; private final UsbSettingsManager mSettingsManager; + private final UsbPermissionManager mPermissionManager; /** * The user id of the current user. There might be several profiles (with separate user ids) @@ -131,23 +132,35 @@ public class UsbService extends IUsbManager.Stub { private final Object mLock = new Object(); - private UsbUserSettingsManager getSettingsForUser(@UserIdInt int userIdInt) { - return mSettingsManager.getSettingsForUser(userIdInt); + /** + * @return the {@link UsbUserSettingsManager} for the given userId + */ + UsbUserSettingsManager getSettingsForUser(@UserIdInt int userId) { + return mSettingsManager.getSettingsForUser(userId); + } + + /** + * @return the {@link UsbUserPermissionManager} for the given userId + */ + UsbUserPermissionManager getPermissionsForUser(@UserIdInt int userId) { + return mPermissionManager.getPermissionsForUser(userId); } public UsbService(Context context) { mContext = context; mUserManager = context.getSystemService(UserManager.class); - mSettingsManager = new UsbSettingsManager(context); + mSettingsManager = new UsbSettingsManager(context, this); + mPermissionManager = new UsbPermissionManager(context, this); mAlsaManager = new UsbAlsaManager(context); final PackageManager pm = mContext.getPackageManager(); if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) { - mHostManager = new UsbHostManager(context, mAlsaManager, mSettingsManager); + mHostManager = new UsbHostManager(context, mAlsaManager, mPermissionManager); } if (new File("/sys/class/android_usb").exists()) { - mDeviceManager = new UsbDeviceManager(context, mAlsaManager, mSettingsManager); + mDeviceManager = new UsbDeviceManager(context, mAlsaManager, mSettingsManager, + mPermissionManager); } if (mHostManager != null || mDeviceManager != null) { mPortManager = new UsbPortManager(context); @@ -255,7 +268,7 @@ public class UsbService extends IUsbManager.Stub { try { synchronized (mLock) { if (mUserManager.isSameProfileGroup(user, mCurrentUserId)) { - fd = mHostManager.openDevice(deviceName, getSettingsForUser(user), + fd = mHostManager.openDevice(deviceName, getPermissionsForUser(user), packageName, uid); } else { Slog.w(TAG, "Cannot open " + deviceName + " for user " + user @@ -292,7 +305,7 @@ public class UsbService extends IUsbManager.Stub { try { synchronized (mLock) { if (mUserManager.isSameProfileGroup(user, mCurrentUserId)) { - return mDeviceManager.openAccessory(accessory, getSettingsForUser(user), + return mDeviceManager.openAccessory(accessory, getPermissionsForUser(user), uid); } else { Slog.w(TAG, "Cannot open " + accessory + " for user " + user @@ -354,7 +367,7 @@ public class UsbService extends IUsbManager.Stub { final long token = Binder.clearCallingIdentity(); try { - return getSettingsForUser(userId).hasPermission(device, packageName, uid); + return getPermissionsForUser(userId).hasPermission(device, packageName, uid); } finally { Binder.restoreCallingIdentity(token); } @@ -367,7 +380,7 @@ public class UsbService extends IUsbManager.Stub { final long token = Binder.clearCallingIdentity(); try { - return getSettingsForUser(userId).hasPermission(accessory, uid); + return getPermissionsForUser(userId).hasPermission(accessory, uid); } finally { Binder.restoreCallingIdentity(token); } @@ -380,7 +393,7 @@ public class UsbService extends IUsbManager.Stub { final long token = Binder.clearCallingIdentity(); try { - getSettingsForUser(userId).requestPermission(device, packageName, pi, uid); + getPermissionsForUser(userId).requestPermission(device, packageName, pi, uid); } finally { Binder.restoreCallingIdentity(token); } @@ -394,7 +407,7 @@ public class UsbService extends IUsbManager.Stub { final long token = Binder.clearCallingIdentity(); try { - getSettingsForUser(userId).requestPermission(accessory, packageName, pi, uid); + getPermissionsForUser(userId).requestPermission(accessory, packageName, pi, uid); } finally { Binder.restoreCallingIdentity(token); } @@ -407,7 +420,7 @@ public class UsbService extends IUsbManager.Stub { final long token = Binder.clearCallingIdentity(); try { - getSettingsForUser(userId).grantDevicePermission(device, uid); + getPermissionsForUser(userId).grantDevicePermission(device, uid); } finally { Binder.restoreCallingIdentity(token); } @@ -420,7 +433,7 @@ public class UsbService extends IUsbManager.Stub { final long token = Binder.clearCallingIdentity(); try { - getSettingsForUser(userId).grantAccessoryPermission(accessory, uid); + getPermissionsForUser(userId).grantAccessoryPermission(accessory, uid); } finally { Binder.restoreCallingIdentity(token); } diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java index 27566f04c280..fbd8782a5d1b 100644 --- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java +++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java @@ -19,15 +19,10 @@ package com.android.server.usb; import android.annotation.NonNull; import android.annotation.UserIdInt; import android.content.Context; -import android.content.Intent; import android.content.pm.UserInfo; -import android.hardware.usb.UsbAccessory; -import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbManager; import android.os.UserHandle; import android.os.UserManager; import android.service.usb.UsbSettingsManagerProto; -import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; @@ -59,8 +54,11 @@ class UsbSettingsManager { private UserManager mUserManager; private UsbHandlerManager mUsbHandlerManager; - public UsbSettingsManager(@NonNull Context context) { + final UsbService mUsbService; + + UsbSettingsManager(@NonNull Context context, UsbService usbService) { mContext = context; + mUsbService = usbService; mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); mUsbHandlerManager = new UsbHandlerManager(context); } @@ -76,8 +74,7 @@ class UsbSettingsManager { synchronized (mSettingsByUser) { UsbUserSettingsManager settings = mSettingsByUser.get(userId); if (settings == null) { - settings = new UsbUserSettingsManager(mContext, UserHandle.of(userId), - new UsbPermissionManager(mContext, UserHandle.of(userId))); + settings = new UsbUserSettingsManager(mContext, UserHandle.of(userId)); mSettingsByUser.put(userId, settings); } return settings; @@ -164,46 +161,4 @@ class UsbSettingsManager { dump.end(token); } - - /** - * Remove temporary access permission and broadcast that a device was removed. - * - * @param device The device that is removed - */ - void usbDeviceRemoved(@NonNull UsbDevice device) { - synchronized (mSettingsByUser) { - for (int i = 0; i < mSettingsByUser.size(); i++) { - // clear temporary permissions for the device - mSettingsByUser.valueAt(i).removeDevicePermissions(device); - } - } - - Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED); - intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - intent.putExtra(UsbManager.EXTRA_DEVICE, device); - - if (DEBUG) { - Slog.d(LOG_TAG, "usbDeviceRemoved, sending " + intent); - } - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); - } - - /** - * Remove temporary access permission and broadcast that a accessory was removed. - * - * @param accessory The accessory that is removed - */ - void usbAccessoryRemoved(@NonNull UsbAccessory accessory) { - synchronized (mSettingsByUser) { - for (int i = 0; i < mSettingsByUser.size(); i++) { - // clear temporary permissions for the accessory - mSettingsByUser.valueAt(i).removeAccessoryPermissions(accessory); - } - } - - Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_DETACHED); - intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); - } } diff --git a/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java b/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java new file mode 100644 index 000000000000..ec7567c40e79 --- /dev/null +++ b/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java @@ -0,0 +1,407 @@ +/* + * Copyright (C) 2018 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 com.android.server.usb; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.PendingIntent; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.hardware.usb.UsbAccessory; +import android.hardware.usb.UsbConstants; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbInterface; +import android.hardware.usb.UsbManager; +import android.os.Binder; +import android.os.Process; +import android.os.UserHandle; +import android.service.usb.UsbSettingsAccessoryPermissionProto; +import android.service.usb.UsbSettingsDevicePermissionProto; +import android.service.usb.UsbUserSettingsManagerProto; +import android.util.Slog; +import android.util.SparseBooleanArray; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.dump.DualDumpOutputStream; + +import java.util.HashMap; + +/** + * UsbUserPermissionManager manages usb device or accessory access permissions. + * + * @hide + */ +class UsbUserPermissionManager { + private static final String LOG_TAG = UsbUserPermissionManager.class.getSimpleName(); + private static final boolean DEBUG = false; + + @GuardedBy("mLock") + /** Temporary mapping USB device name to list of UIDs with permissions for the device*/ + private final HashMap<String, SparseBooleanArray> mDevicePermissionMap = + new HashMap<>(); + @GuardedBy("mLock") + /** Temporary mapping UsbAccessory to list of UIDs with permissions for the accessory*/ + private final HashMap<UsbAccessory, SparseBooleanArray> mAccessoryPermissionMap = + new HashMap<>(); + + private final Context mContext; + private final UserHandle mUser; + private final UsbUserSettingsManager mUsbUserSettingsManager; + private final boolean mDisablePermissionDialogs; + + private final Object mLock = new Object(); + + UsbUserPermissionManager(@NonNull Context context, @NonNull UserHandle user, + @NonNull UsbUserSettingsManager usbUserSettingsManager) { + mContext = context; + mUser = user; + mUsbUserSettingsManager = usbUserSettingsManager; + mDisablePermissionDialogs = context.getResources().getBoolean( + com.android.internal.R.bool.config_disableUsbPermissionDialogs); + } + + /** + * Removes access permissions of all packages for the USB accessory. + * + * @param accessory to remove permissions for + */ + void removeAccessoryPermissions(@NonNull UsbAccessory accessory) { + synchronized (mLock) { + mAccessoryPermissionMap.remove(accessory); + } + } + + /** + * Removes access permissions of all packages for the USB device. + * + * @param device to remove permissions for + */ + void removeDevicePermissions(@NonNull UsbDevice device) { + synchronized (mLock) { + mDevicePermissionMap.remove(device.getDeviceName()); + } + } + + /** + * Grants permission for USB device without showing system dialog for package with uid. + * + * @param device to grant permission for + * @param uid to grant permission for + */ + void grantDevicePermission(@NonNull UsbDevice device, int uid) { + synchronized (mLock) { + String deviceName = device.getDeviceName(); + SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName); + if (uidList == null) { + uidList = new SparseBooleanArray(1); + mDevicePermissionMap.put(deviceName, uidList); + } + uidList.put(uid, true); + } + } + + /** + * Grants permission for USB accessory without showing system dialog for package with uid. + * + * @param accessory to grant permission for + * @param uid to grant permission for + */ + void grantAccessoryPermission(@NonNull UsbAccessory accessory, int uid) { + synchronized (mLock) { + SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory); + if (uidList == null) { + uidList = new SparseBooleanArray(1); + mAccessoryPermissionMap.put(accessory, uidList); + } + uidList.put(uid, true); + } + } + + /** + * Returns true if package with uid has permission to access the device. + * + * @param device to check permission for + * @param uid to check permission for + * @return {@code true} if package with uid has permission + */ + boolean hasPermission(@NonNull UsbDevice device, int uid) { + synchronized (mLock) { + if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) { + return true; + } + SparseBooleanArray uidList = mDevicePermissionMap.get(device.getDeviceName()); + if (uidList == null) { + return false; + } + return uidList.get(uid); + } + } + + /** + * Returns true if caller has permission to access the accessory. + * + * @param accessory to check permission for + * @param uid to check permission for + * @return {@code true} if caller has permssion + */ + boolean hasPermission(@NonNull UsbAccessory accessory, int uid) { + synchronized (mLock) { + if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) { + return true; + } + SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory); + if (uidList == null) { + return false; + } + return uidList.get(uid); + } + } + + boolean hasPermission(UsbDevice device, String packageName, int uid) { + if (isCameraDevicePresent(device)) { + if (!isCameraPermissionGranted(packageName, uid)) { + return false; + } + } + + return hasPermission(device, uid); + } + + /** + * Creates UI dialog to request permission for the given package to access the device + * or accessory. + * + * @param device The USB device attached + * @param accessory The USB accessory attached + * @param canBeDefault Whether the calling pacakge can set as default handler + * of the USB device or accessory + * @param packageName The package name of the calling package + * @param uid The uid of the calling package + * @param userContext The context to start the UI dialog + * @param pi PendingIntent for returning result + */ + void requestPermissionDialog(@Nullable UsbDevice device, + @Nullable UsbAccessory accessory, + boolean canBeDefault, + @NonNull String packageName, + int uid, + @NonNull Context userContext, + @NonNull PendingIntent pi) { + long identity = Binder.clearCallingIdentity(); + Intent intent = new Intent(); + if (device != null) { + intent.putExtra(UsbManager.EXTRA_DEVICE, device); + } else { + intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); + } + intent.putExtra(Intent.EXTRA_INTENT, pi); + intent.putExtra(Intent.EXTRA_UID, uid); + intent.putExtra(UsbManager.EXTRA_CAN_BE_DEFAULT, canBeDefault); + intent.putExtra(UsbManager.EXTRA_PACKAGE, packageName); + intent.setClassName("com.android.systemui", + "com.android.systemui.usb.UsbPermissionActivity"); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + try { + userContext.startActivityAsUser(intent, mUser); + } catch (ActivityNotFoundException e) { + Slog.e(LOG_TAG, "unable to start UsbPermissionActivity"); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + void dump(@NonNull DualDumpOutputStream dump) { + synchronized (mLock) { + for (String deviceName : mDevicePermissionMap.keySet()) { + long devicePermissionToken = dump.start("device_permissions", + UsbUserSettingsManagerProto.DEVICE_PERMISSIONS); + + dump.write("device_name", UsbSettingsDevicePermissionProto.DEVICE_NAME, deviceName); + + SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName); + int count = uidList.size(); + for (int i = 0; i < count; i++) { + dump.write("uids", UsbSettingsDevicePermissionProto.UIDS, uidList.keyAt(i)); + } + + dump.end(devicePermissionToken); + } + + for (UsbAccessory accessory : mAccessoryPermissionMap.keySet()) { + long accessoryPermissionToken = dump.start("accessory_permissions", + UsbUserSettingsManagerProto.ACCESSORY_PERMISSIONS); + + dump.write("accessory_description", + UsbSettingsAccessoryPermissionProto.ACCESSORY_DESCRIPTION, + accessory.getDescription()); + + SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory); + int count = uidList.size(); + for (int i = 0; i < count; i++) { + dump.write("uids", UsbSettingsAccessoryPermissionProto.UIDS, uidList.keyAt(i)); + } + + dump.end(accessoryPermissionToken); + } + } + } + + /** + * Check for camera permission of the calling process. + * + * @param packageName Package name of the caller. + * @param uid Linux uid of the calling process. + * + * @return True in case camera permission is available, False otherwise. + */ + private boolean isCameraPermissionGranted(String packageName, int uid) { + int targetSdkVersion = android.os.Build.VERSION_CODES.P; + try { + ApplicationInfo aInfo = mContext.getPackageManager().getApplicationInfo(packageName, 0); + // compare uid with packageName to foil apps pretending to be someone else + if (aInfo.uid != uid) { + Slog.i(LOG_TAG, "Package " + packageName + " does not match caller's uid " + uid); + return false; + } + targetSdkVersion = aInfo.targetSdkVersion; + } catch (PackageManager.NameNotFoundException e) { + Slog.i(LOG_TAG, "Package not found, likely due to invalid package name!"); + return false; + } + + if (targetSdkVersion >= android.os.Build.VERSION_CODES.P) { + int allowed = mContext.checkCallingPermission(android.Manifest.permission.CAMERA); + if (android.content.pm.PackageManager.PERMISSION_DENIED == allowed) { + Slog.i(LOG_TAG, "Camera permission required for USB video class devices"); + return false; + } + } + + return true; + } + + public void checkPermission(UsbDevice device, String packageName, int uid) { + if (!hasPermission(device, packageName, uid)) { + throw new SecurityException("User has not given " + uid + "/" + packageName + + " permission to access device " + device.getDeviceName()); + } + } + + public void checkPermission(UsbAccessory accessory, int uid) { + if (!hasPermission(accessory, uid)) { + throw new SecurityException("User has not given " + uid + " permission to accessory " + + accessory); + } + } + + private void requestPermissionDialog(@Nullable UsbDevice device, + @Nullable UsbAccessory accessory, + boolean canBeDefault, + String packageName, + PendingIntent pi, + int uid) { + // compare uid with packageName to foil apps pretending to be someone else + try { + ApplicationInfo aInfo = mContext.getPackageManager().getApplicationInfo(packageName, 0); + if (aInfo.uid != uid) { + throw new IllegalArgumentException("package " + packageName + + " does not match caller's uid " + uid); + } + } catch (PackageManager.NameNotFoundException e) { + throw new IllegalArgumentException("package " + packageName + " not found"); + } + + requestPermissionDialog(device, accessory, canBeDefault, packageName, uid, mContext, pi); + } + + public void requestPermission(UsbDevice device, String packageName, PendingIntent pi, int uid) { + Intent intent = new Intent(); + + // respond immediately if permission has already been granted + if (hasPermission(device, packageName, uid)) { + intent.putExtra(UsbManager.EXTRA_DEVICE, device); + intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true); + try { + pi.send(mContext, 0, intent); + } catch (PendingIntent.CanceledException e) { + if (DEBUG) Slog.d(LOG_TAG, "requestPermission PendingIntent was cancelled"); + } + return; + } + if (isCameraDevicePresent(device)) { + if (!isCameraPermissionGranted(packageName, uid)) { + intent.putExtra(UsbManager.EXTRA_DEVICE, device); + intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false); + try { + pi.send(mContext, 0, intent); + } catch (PendingIntent.CanceledException e) { + if (DEBUG) Slog.d(LOG_TAG, "requestPermission PendingIntent was cancelled"); + } + return; + } + } + + requestPermissionDialog(device, null, + mUsbUserSettingsManager.canBeDefault(device, packageName), packageName, pi, uid); + } + + public void requestPermission(UsbAccessory accessory, String packageName, PendingIntent pi, + int uid) { + // respond immediately if permission has already been granted + if (hasPermission(accessory, uid)) { + Intent intent = new Intent(); + intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); + intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true); + try { + pi.send(mContext, 0, intent); + } catch (PendingIntent.CanceledException e) { + if (DEBUG) Slog.d(LOG_TAG, "requestPermission PendingIntent was cancelled"); + } + return; + } + + requestPermissionDialog(null, accessory, + mUsbUserSettingsManager.canBeDefault(accessory, packageName), packageName, pi, uid); + } + + /** + * Check whether a particular device or any of its interfaces + * is of class VIDEO. + * + * @param device The device that needs to get scanned + * @return True in case a VIDEO device or interface is present, + * False otherwise. + */ + private boolean isCameraDevicePresent(UsbDevice device) { + if (device.getDeviceClass() == UsbConstants.USB_CLASS_VIDEO) { + return true; + } + + for (int i = 0; i < device.getInterfaceCount(); i++) { + UsbInterface iface = device.getInterface(i); + if (iface.getInterfaceClass() == UsbConstants.USB_CLASS_VIDEO) { + return true; + } + } + + return false; + } +} diff --git a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java index 84add88cc84c..c2b8d0109e68 100644 --- a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java +++ b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java @@ -21,13 +21,10 @@ import static com.android.server.usb.UsbProfileGroupSettingsManager.getAccessory import static com.android.server.usb.UsbProfileGroupSettingsManager.getDeviceFilters; import android.annotation.NonNull; -import android.annotation.Nullable; -import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; -import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; @@ -36,9 +33,7 @@ import android.content.res.XmlResourceParser; import android.hardware.usb.AccessoryFilter; import android.hardware.usb.DeviceFilter; import android.hardware.usb.UsbAccessory; -import android.hardware.usb.UsbConstants; import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbInterface; import android.hardware.usb.UsbManager; import android.os.UserHandle; import android.service.usb.UsbAccessoryAttachedActivities; @@ -62,12 +57,10 @@ class UsbUserSettingsManager { private final Context mUserContext; private final PackageManager mPackageManager; - private final UsbPermissionManager mUsbPermissionManager; private final Object mLock = new Object(); - UsbUserSettingsManager(Context context, UserHandle user, - @NonNull UsbPermissionManager usbPermissionManager) { + UsbUserSettingsManager(Context context, UserHandle user) { if (DEBUG) Slog.v(TAG, "Creating settings for " + user); try { @@ -79,189 +72,6 @@ class UsbUserSettingsManager { mPackageManager = mUserContext.getPackageManager(); mUser = user; - mUsbPermissionManager = usbPermissionManager; - } - - /** - * Remove all access permission for a device. - * - * @param device The device the permissions are for - */ - void removeDevicePermissions(@NonNull UsbDevice device) { - mUsbPermissionManager.removeDevicePermissions(device); - } - - /** - * Remove all access permission for a accessory. - * - * @param accessory The accessory the permissions are for - */ - void removeAccessoryPermissions(@NonNull UsbAccessory accessory) { - mUsbPermissionManager.removeAccessoryPermissions(accessory); - } - - /** - * Check whether a particular device or any of its interfaces - * is of class VIDEO. - * - * @param device The device that needs to get scanned - * @return True in case a VIDEO device or interface is present, - * False otherwise. - */ - private boolean isCameraDevicePresent(UsbDevice device) { - if (device.getDeviceClass() == UsbConstants.USB_CLASS_VIDEO) { - return true; - } - - for (int i = 0; i < device.getInterfaceCount(); i++) { - UsbInterface iface = device.getInterface(i); - if (iface.getInterfaceClass() == UsbConstants.USB_CLASS_VIDEO) { - return true; - } - } - - return false; - } - - /** - * Check for camera permission of the calling process. - * - * @param packageName Package name of the caller. - * @param uid Linux uid of the calling process. - * - * @return True in case camera permission is available, False otherwise. - */ - private boolean isCameraPermissionGranted(String packageName, int uid) { - int targetSdkVersion = android.os.Build.VERSION_CODES.P; - try { - ApplicationInfo aInfo = mPackageManager.getApplicationInfo(packageName, 0); - // compare uid with packageName to foil apps pretending to be someone else - if (aInfo.uid != uid) { - Slog.i(TAG, "Package " + packageName + " does not match caller's uid " + uid); - return false; - } - targetSdkVersion = aInfo.targetSdkVersion; - } catch (PackageManager.NameNotFoundException e) { - Slog.i(TAG, "Package not found, likely due to invalid package name!"); - return false; - } - - if (targetSdkVersion >= android.os.Build.VERSION_CODES.P) { - int allowed = mUserContext.checkCallingPermission(android.Manifest.permission.CAMERA); - if (android.content.pm.PackageManager.PERMISSION_DENIED == allowed) { - Slog.i(TAG, "Camera permission required for USB video class devices"); - return false; - } - } - - return true; - } - - public boolean hasPermission(UsbDevice device, String packageName, int uid) { - if (isCameraDevicePresent(device)) { - if (!isCameraPermissionGranted(packageName, uid)) { - return false; - } - } - - return mUsbPermissionManager.hasPermission(device, uid); - } - - public boolean hasPermission(UsbAccessory accessory, int uid) { - return mUsbPermissionManager.hasPermission(accessory, uid); - } - - public void checkPermission(UsbDevice device, String packageName, int uid) { - if (!hasPermission(device, packageName, uid)) { - throw new SecurityException("User has not given " + uid + "/" + packageName - + " permission to access device " + device.getDeviceName()); - } - } - - public void checkPermission(UsbAccessory accessory, int uid) { - if (!hasPermission(accessory, uid)) { - throw new SecurityException("User has not given " + uid + " permission to accessory " - + accessory); - } - } - - private void requestPermissionDialog(@Nullable UsbDevice device, - @Nullable UsbAccessory accessory, - boolean canBeDefault, - String packageName, - PendingIntent pi, - int uid) { - // compare uid with packageName to foil apps pretending to be someone else - try { - ApplicationInfo aInfo = mPackageManager.getApplicationInfo(packageName, 0); - if (aInfo.uid != uid) { - throw new IllegalArgumentException("package " + packageName + - " does not match caller's uid " + uid); - } - } catch (PackageManager.NameNotFoundException e) { - throw new IllegalArgumentException("package " + packageName + " not found"); - } - - mUsbPermissionManager.requestPermissionDialog(device, - accessory, canBeDefault, packageName, uid, mUserContext, pi); - } - - public void requestPermission(UsbDevice device, String packageName, PendingIntent pi, int uid) { - Intent intent = new Intent(); - - // respond immediately if permission has already been granted - if (hasPermission(device, packageName, uid)) { - intent.putExtra(UsbManager.EXTRA_DEVICE, device); - intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true); - try { - pi.send(mUserContext, 0, intent); - } catch (PendingIntent.CanceledException e) { - if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled"); - } - return; - } - if (isCameraDevicePresent(device)) { - if (!isCameraPermissionGranted(packageName, uid)) { - intent.putExtra(UsbManager.EXTRA_DEVICE, device); - intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false); - try { - pi.send(mUserContext, 0, intent); - } catch (PendingIntent.CanceledException e) { - if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled"); - } - return; - } - } - - requestPermissionDialog(device, null, canBeDefault(device, packageName), packageName, pi, - uid); - } - - public void requestPermission(UsbAccessory accessory, String packageName, PendingIntent pi, - int uid) { - // respond immediately if permission has already been granted - if (hasPermission(accessory, uid)) { - Intent intent = new Intent(); - intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); - intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true); - try { - pi.send(mUserContext, 0, intent); - } catch (PendingIntent.CanceledException e) { - if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled"); - } - return; - } - - requestPermissionDialog(null, accessory, canBeDefault(accessory, packageName), packageName, - pi, uid); - } - - public void grantDevicePermission(UsbDevice device, int uid) { - mUsbPermissionManager.grantDevicePermission(device, uid); - } - - public void grantAccessoryPermission(UsbAccessory accessory, int uid) { - mUsbPermissionManager.grantAccessoryPermission(accessory, uid); } /** @@ -285,7 +95,7 @@ class UsbUserSettingsManager { * * @return {@code true} if the app can be default */ - private boolean canBeDefault(@NonNull UsbDevice device, String packageName) { + boolean canBeDefault(@NonNull UsbDevice device, String packageName) { ActivityInfo[] activities = getPackageActivities(packageName); if (activities != null) { int numActivities = activities.length; @@ -327,7 +137,7 @@ class UsbUserSettingsManager { * * @return {@code true} if the app can be default */ - private boolean canBeDefault(@NonNull UsbAccessory accessory, String packageName) { + boolean canBeDefault(@NonNull UsbAccessory accessory, String packageName) { ActivityInfo[] activities = getPackageActivities(packageName); if (activities != null) { int numActivities = activities.length; @@ -377,8 +187,6 @@ class UsbUserSettingsManager { synchronized (mLock) { dump.write("user_id", UsbUserSettingsManagerProto.USER_ID, mUser.getIdentifier()); - mUsbPermissionManager.dump(dump); - List<ResolveInfo> deviceAttachedActivities = queryIntentActivities( new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED)); int numDeviceAttachedActivities = deviceAttachedActivities.size(); |