Merge "Separate Usb permissions from Usb settings"

This commit is contained in:
Evan Severson
2019-08-23 16:51:16 +00:00
committed by Android (Google) Code Review
10 changed files with 549 additions and 494 deletions

View File

@@ -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();
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}
void remove(@NonNull UserHandle userToRemove) {
synchronized (mPermissionsByUser) {
mPermissionsByUser.remove(userToRemove.getIdentifier());
}
}
/**
* Removes access permissions of all packages for the USB device.
* Remove temporary access permission and broadcast that a device was removed.
*
* @param device to remove permissions for
* @param device The device that is removed
*/
void removeDevicePermissions(@NonNull UsbDevice device) {
synchronized (mLock) {
mDevicePermissionMap.remove(device.getDeviceName());
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);
}
}
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);
}
/**
* Grants permission for USB device without showing system dialog for package with uid.
* Remove temporary access permission and broadcast that a accessory was removed.
*
* @param device to grant permission for
* @param uid to grant permission for
* @param accessory The accessory 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 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);
}
uidList.put(uid, true);
}
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);
}
/**
* 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);
}
}
/**
* 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);
}
}
}
}

View File

@@ -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);
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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();

View File

@@ -63,6 +63,8 @@ public class UsbHandlerTest {
@Mock
private UsbSettingsManager mUsbSettingsManager;
@Mock
private UsbPermissionManager mUsbPermissionManager;
@Mock
private SharedPreferences mSharedPreferences;
@Mock
private SharedPreferences.Editor mEditor;
@@ -87,8 +89,9 @@ public class UsbHandlerTest {
Intent mBroadcastedIntent;
MockUsbHandler(Looper looper, Context context, UsbDeviceManager deviceManager,
UsbAlsaManager alsaManager, UsbSettingsManager settingsManager) {
super(looper, context, deviceManager, alsaManager, settingsManager);
UsbAlsaManager alsaManager, UsbSettingsManager settingsManager,
UsbPermissionManager permissionManager) {
super(looper, context, deviceManager, alsaManager, permissionManager);
mUseUsbNotification = false;
mIsUsbTransferAllowed = true;
mCurrentUsbFunctionsReceived = true;
@@ -142,7 +145,7 @@ public class UsbHandlerTest {
mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(),
InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbAlsaManager,
mUsbSettingsManager);
mUsbSettingsManager, mUsbPermissionManager);
}
@SmallTest
@@ -205,7 +208,7 @@ public class UsbHandlerTest {
UsbManager.USB_FUNCTION_ADB);
mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(),
InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbAlsaManager,
mUsbSettingsManager);
mUsbSettingsManager, mUsbPermissionManager);
sendBootCompleteMessages(mUsbHandler);
mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_ENABLE_ADB, 0));
@@ -228,7 +231,7 @@ public class UsbHandlerTest {
mMockProperties.put(UsbDeviceManager.UsbHandler.USB_PERSISTENT_CONFIG_PROPERTY, "adb");
mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(),
InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbAlsaManager,
mUsbSettingsManager);
mUsbSettingsManager, mUsbPermissionManager);
sendBootCompleteMessages(mUsbHandler);
assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
@@ -316,7 +319,7 @@ public class UsbHandlerTest {
.thenReturn(UsbManager.USB_FUNCTION_MTP);
mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(),
InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbAlsaManager,
mUsbSettingsManager);
mUsbSettingsManager, mUsbPermissionManager);
sendBootCompleteMessages(mUsbHandler);
mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_SCREEN_LOCK, 1));
mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_SCREEN_LOCK, 0));