Loading services/usb/java/com/android/server/usb/UsbDeviceManager.java +14 −14 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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()) { Loading Loading @@ -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; Loading @@ -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(); Loading Loading @@ -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( Loading Loading @@ -663,7 +663,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser if (mCurrentAccessory != null) { if (mBootCompleted) { mSettingsManager.usbAccessoryRemoved(mCurrentAccessory); mPermissionManager.usbAccessoryRemoved(mCurrentAccessory); } mCurrentAccessory = null; } Loading Loading @@ -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. Loading Loading @@ -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(); Loading Loading @@ -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"); Loading @@ -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(); } Loading services/usb/java/com/android/server/usb/UsbHostManager.java +12 −10 Original line number Diff line number Diff line Loading @@ -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") Loading Loading @@ -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)) { Loading Loading @@ -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); Loading Loading @@ -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 Loading Loading @@ -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"); Loading @@ -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); } } Loading services/usb/java/com/android/server/usb/UsbPermissionManager.java +50 −185 Original line number Diff line number Diff line /* * 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. Loading @@ -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); } /** * 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()); return permissions; } } /** * 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); void remove(@NonNull UserHandle userToRemove) { synchronized (mPermissionsByUser) { mPermissionsByUser.remove(userToRemove.getIdentifier()); } } /** * Grants permission for USB accessory without showing system dialog for package with uid. * Remove temporary access permission and broadcast that a device was removed. * * @param accessory to grant permission for * @param uid to grant permission for * @param device The device that is removed */ 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); 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); } } /** * 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); } } 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 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); if (DEBUG) { Slog.d(LOG_TAG, "usbDeviceRemoved, sending " + intent); } mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } /** * Creates UI dialog to request permission for the given package to access the device * or accessory. * Remove temporary access permission and broadcast that a accessory was removed. * * @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 * @param accessory The accessory that is removed */ 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 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); } 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)); 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); } dump.end(accessoryPermissionToken); } } } } services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java +7 −6 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -844,14 +844,15 @@ class UsbProfileGroupSettingsManager { } if (defaultActivity != null) { UsbUserSettingsManager defaultRIUserSettings = mSettingsManager.getSettingsForUser( 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); } Loading services/usb/java/com/android/server/usb/UsbSerialReader.java +8 −7 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; } Loading Loading @@ -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); } } } Loading Loading
services/usb/java/com/android/server/usb/UsbDeviceManager.java +14 −14 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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()) { Loading Loading @@ -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; Loading @@ -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(); Loading Loading @@ -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( Loading Loading @@ -663,7 +663,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser if (mCurrentAccessory != null) { if (mBootCompleted) { mSettingsManager.usbAccessoryRemoved(mCurrentAccessory); mPermissionManager.usbAccessoryRemoved(mCurrentAccessory); } mCurrentAccessory = null; } Loading Loading @@ -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. Loading Loading @@ -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(); Loading Loading @@ -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"); Loading @@ -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(); } Loading
services/usb/java/com/android/server/usb/UsbHostManager.java +12 −10 Original line number Diff line number Diff line Loading @@ -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") Loading Loading @@ -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)) { Loading Loading @@ -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); Loading Loading @@ -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 Loading Loading @@ -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"); Loading @@ -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); } } Loading
services/usb/java/com/android/server/usb/UsbPermissionManager.java +50 −185 Original line number Diff line number Diff line /* * 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. Loading @@ -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); } /** * 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()); return permissions; } } /** * 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); void remove(@NonNull UserHandle userToRemove) { synchronized (mPermissionsByUser) { mPermissionsByUser.remove(userToRemove.getIdentifier()); } } /** * Grants permission for USB accessory without showing system dialog for package with uid. * Remove temporary access permission and broadcast that a device was removed. * * @param accessory to grant permission for * @param uid to grant permission for * @param device The device that is removed */ 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); 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); } } /** * 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); } } 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 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); if (DEBUG) { Slog.d(LOG_TAG, "usbDeviceRemoved, sending " + intent); } mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } /** * Creates UI dialog to request permission for the given package to access the device * or accessory. * Remove temporary access permission and broadcast that a accessory was removed. * * @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 * @param accessory The accessory that is removed */ 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 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); } 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)); 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); } dump.end(accessoryPermissionToken); } } } }
services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java +7 −6 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -844,14 +844,15 @@ class UsbProfileGroupSettingsManager { } if (defaultActivity != null) { UsbUserSettingsManager defaultRIUserSettings = mSettingsManager.getSettingsForUser( 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); } Loading
services/usb/java/com/android/server/usb/UsbSerialReader.java +8 −7 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; } Loading Loading @@ -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); } } } Loading