Merge "Check camera permissions for any devices using the VIDEO class"
This commit is contained in:
committed by
Android (Google) Code Review
commit
e19dc30bd3
@@ -34,7 +34,7 @@ interface IUsbManager
|
||||
/* Returns a file descriptor for communicating with the USB device.
|
||||
* The native fd can be passed to usb_device_new() in libusbhost.
|
||||
*/
|
||||
ParcelFileDescriptor openDevice(String deviceName);
|
||||
ParcelFileDescriptor openDevice(String deviceName, String packageName);
|
||||
|
||||
/* Returns the currently attached USB accessory */
|
||||
UsbAccessory getCurrentAccessory();
|
||||
@@ -55,7 +55,7 @@ interface IUsbManager
|
||||
void setAccessoryPackage(in UsbAccessory accessory, String packageName, int userId);
|
||||
|
||||
/* Returns true if the caller has permission to access the device. */
|
||||
boolean hasDevicePermission(in UsbDevice device);
|
||||
boolean hasDevicePermission(in UsbDevice device, String packageName);
|
||||
|
||||
/* Returns true if the caller has permission to access the accessory. */
|
||||
boolean hasAccessoryPermission(in UsbAccessory accessory);
|
||||
|
||||
@@ -344,7 +344,7 @@ public class UsbManager {
|
||||
public UsbDeviceConnection openDevice(UsbDevice device) {
|
||||
try {
|
||||
String deviceName = device.getDeviceName();
|
||||
ParcelFileDescriptor pfd = mService.openDevice(deviceName);
|
||||
ParcelFileDescriptor pfd = mService.openDevice(deviceName, mContext.getPackageName());
|
||||
if (pfd != null) {
|
||||
UsbDeviceConnection connection = new UsbDeviceConnection(device);
|
||||
boolean result = connection.open(deviceName, pfd, mContext);
|
||||
@@ -400,6 +400,9 @@ public class UsbManager {
|
||||
* Permission might have been granted temporarily via
|
||||
* {@link #requestPermission(UsbDevice, PendingIntent)} or
|
||||
* by the user choosing the caller as the default application for the device.
|
||||
* Permission for USB devices of class {@link UsbConstants#USB_CLASS_VIDEO} for clients that
|
||||
* target SDK {@link android.os.Build.VERSION_CODES#P} and above can be granted only if they
|
||||
* have additionally the {@link android.Manifest.permission#CAMERA} permission.
|
||||
*
|
||||
* @param device to check permissions for
|
||||
* @return true if caller has permission
|
||||
@@ -409,7 +412,7 @@ public class UsbManager {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return mService.hasDevicePermission(device);
|
||||
return mService.hasDevicePermission(device, mContext.getPackageName());
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
@@ -450,6 +453,10 @@ public class UsbManager {
|
||||
* permission was granted by the user
|
||||
* </ul>
|
||||
*
|
||||
* Permission for USB devices of class {@link UsbConstants#USB_CLASS_VIDEO} for clients that
|
||||
* target SDK {@link android.os.Build.VERSION_CODES#P} and above can be granted only if they
|
||||
* have additionally the {@link android.Manifest.permission#CAMERA} permission.
|
||||
*
|
||||
* @param device to request permissions for
|
||||
* @param pi PendingIntent for returning result
|
||||
*/
|
||||
|
||||
@@ -323,7 +323,8 @@ public class UsbHostManager {
|
||||
}
|
||||
|
||||
/* Opens the specified USB device */
|
||||
public ParcelFileDescriptor openDevice(String deviceName, UsbUserSettingsManager settings) {
|
||||
public ParcelFileDescriptor openDevice(String deviceName, UsbUserSettingsManager settings,
|
||||
String packageName, int uid) {
|
||||
synchronized (mLock) {
|
||||
if (isBlackListed(deviceName)) {
|
||||
throw new SecurityException("USB device is on a restricted bus");
|
||||
@@ -334,7 +335,7 @@ public class UsbHostManager {
|
||||
throw new IllegalArgumentException(
|
||||
"device " + deviceName + " does not exist or is restricted");
|
||||
}
|
||||
settings.checkPermission(device);
|
||||
settings.checkPermission(device, packageName, uid);
|
||||
return nativeOpenDevice(deviceName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ public class UsbService extends IUsbManager.Stub {
|
||||
|
||||
/* Opens the specified USB device (host mode) */
|
||||
@Override
|
||||
public ParcelFileDescriptor openDevice(String deviceName) {
|
||||
public ParcelFileDescriptor openDevice(String deviceName, String packageName) {
|
||||
ParcelFileDescriptor fd = null;
|
||||
|
||||
if (mHostManager != null) {
|
||||
@@ -242,7 +242,8 @@ public class UsbService extends IUsbManager.Stub {
|
||||
boolean isCurrentUser = isCallerInCurrentUserProfileGroupLocked();
|
||||
|
||||
if (isCurrentUser) {
|
||||
fd = mHostManager.openDevice(deviceName, getSettingsForUser(userIdInt));
|
||||
fd = mHostManager.openDevice(deviceName, getSettingsForUser(userIdInt),
|
||||
packageName, Binder.getCallingUid());
|
||||
} else {
|
||||
Slog.w(TAG, "Cannot open " + deviceName + " for user " + userIdInt +
|
||||
" as user is not active.");
|
||||
@@ -308,9 +309,10 @@ public class UsbService extends IUsbManager.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDevicePermission(UsbDevice device) {
|
||||
public boolean hasDevicePermission(UsbDevice device, String packageName) {
|
||||
final int userId = UserHandle.getCallingUserId();
|
||||
return getSettingsForUser(userId).hasPermission(device);
|
||||
return getSettingsForUser(userId).hasPermission(device, packageName,
|
||||
Binder.getCallingUid());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -322,7 +324,8 @@ public class UsbService extends IUsbManager.Stub {
|
||||
@Override
|
||||
public void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) {
|
||||
final int userId = UserHandle.getCallingUserId();
|
||||
getSettingsForUser(userId).requestPermission(device, packageName, pi);
|
||||
getSettingsForUser(userId).requestPermission(device, packageName, pi,
|
||||
Binder.getCallingUid());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,6 +26,8 @@ import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.hardware.usb.UsbAccessory;
|
||||
import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbInterface;
|
||||
import android.hardware.usb.UsbConstants;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Process;
|
||||
@@ -95,10 +97,70 @@ class UsbUserSettingsManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
public boolean hasPermission(UsbDevice device) {
|
||||
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) {
|
||||
synchronized (mLock) {
|
||||
int uid = Binder.getCallingUid();
|
||||
if (isCameraDevicePresent(device)) {
|
||||
if (!isCameraPermissionGranted(packageName, uid)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
|
||||
return true;
|
||||
}
|
||||
@@ -124,8 +186,8 @@ class UsbUserSettingsManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void checkPermission(UsbDevice device) {
|
||||
if (!hasPermission(device)) {
|
||||
public void checkPermission(UsbDevice device, String packageName, int uid) {
|
||||
if (!hasPermission(device, packageName, uid)) {
|
||||
throw new SecurityException("User has not given permission to device " + device);
|
||||
}
|
||||
}
|
||||
@@ -166,11 +228,11 @@ class UsbUserSettingsManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void requestPermission(UsbDevice device, String packageName, PendingIntent 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)) {
|
||||
if (hasPermission(device, packageName, uid)) {
|
||||
intent.putExtra(UsbManager.EXTRA_DEVICE, device);
|
||||
intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
|
||||
try {
|
||||
@@ -180,6 +242,18 @@ class UsbUserSettingsManager {
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// start UsbPermissionActivity so user can choose an activity
|
||||
intent.putExtra(UsbManager.EXTRA_DEVICE, device);
|
||||
|
||||
Reference in New Issue
Block a user