summaryrefslogtreecommitdiff
path: root/services/usb/java
diff options
context:
space:
mode:
authorEvan Severson <evanseverson@google.com>2019-08-23 16:51:16 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2019-08-23 16:51:16 +0000
commit9727c0581a456a6ea18c7858d69b9f2de18af9f4 (patch)
tree7292e165f057b4e41ed3b6883dad2381961ed479 /services/usb/java
parent903102c43014cccea9d0365a0700bd617faf2453 (diff)
parente05005b18f87215f0d9274a12dae6fde9ad8a23d (diff)
Merge "Separate Usb permissions from Usb settings"
Diffstat (limited to 'services/usb/java')
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java28
-rw-r--r--services/usb/java/com/android/server/usb/UsbHostManager.java22
-rw-r--r--services/usb/java/com/android/server/usb/UsbPermissionManager.java235
-rw-r--r--services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java13
-rw-r--r--services/usb/java/com/android/server/usb/UsbSerialReader.java15
-rw-r--r--services/usb/java/com/android/server/usb/UsbService.java39
-rw-r--r--services/usb/java/com/android/server/usb/UsbSettingsManager.java55
-rw-r--r--services/usb/java/com/android/server/usb/UsbUserPermissionManager.java407
-rw-r--r--services/usb/java/com/android/server/usb/UsbUserSettingsManager.java198
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();