Merge "Disallow usb access to camera and mic devices if global privacy toggle is active" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c20398b8d1
@@ -25,12 +25,12 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.hardware.SensorPrivacyManager.Sensors;
|
||||||
|
import android.hardware.SensorPrivacyManagerInternal;
|
||||||
import android.hardware.usb.AccessoryFilter;
|
import android.hardware.usb.AccessoryFilter;
|
||||||
import android.hardware.usb.DeviceFilter;
|
import android.hardware.usb.DeviceFilter;
|
||||||
import android.hardware.usb.UsbAccessory;
|
import android.hardware.usb.UsbAccessory;
|
||||||
import android.hardware.usb.UsbConstants;
|
|
||||||
import android.hardware.usb.UsbDevice;
|
import android.hardware.usb.UsbDevice;
|
||||||
import android.hardware.usb.UsbInterface;
|
|
||||||
import android.hardware.usb.UsbManager;
|
import android.hardware.usb.UsbManager;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
@@ -52,9 +52,9 @@ import android.util.TypedXmlSerializer;
|
|||||||
import android.util.Xml;
|
import android.util.Xml;
|
||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
import com.android.internal.util.FastXmlSerializer;
|
|
||||||
import com.android.internal.util.XmlUtils;
|
import com.android.internal.util.XmlUtils;
|
||||||
import com.android.internal.util.dump.DualDumpOutputStream;
|
import com.android.internal.util.dump.DualDumpOutputStream;
|
||||||
|
import com.android.server.LocalServices;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
@@ -64,7 +64,6 @@ import java.io.FileInputStream;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UsbUserPermissionManager manages usb device or accessory access permissions.
|
* UsbUserPermissionManager manages usb device or accessory access permissions.
|
||||||
@@ -110,19 +109,20 @@ class UsbUserPermissionManager {
|
|||||||
*/
|
*/
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private boolean mIsCopyPermissionsScheduled;
|
private boolean mIsCopyPermissionsScheduled;
|
||||||
|
private final SensorPrivacyManagerInternal mSensorPrivacyMgrInternal;
|
||||||
|
|
||||||
UsbUserPermissionManager(@NonNull Context context,
|
UsbUserPermissionManager(@NonNull Context context,
|
||||||
@NonNull UsbUserSettingsManager usbUserSettingsManager) {
|
@NonNull UsbUserSettingsManager usbUserSettingsManager) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mUser = context.getUser();
|
mUser = context.getUser();
|
||||||
mUsbUserSettingsManager = usbUserSettingsManager;
|
mUsbUserSettingsManager = usbUserSettingsManager;
|
||||||
|
mSensorPrivacyMgrInternal = LocalServices.getService(SensorPrivacyManagerInternal.class);
|
||||||
mDisablePermissionDialogs = context.getResources().getBoolean(
|
mDisablePermissionDialogs = context.getResources().getBoolean(
|
||||||
com.android.internal.R.bool.config_disableUsbPermissionDialogs);
|
com.android.internal.R.bool.config_disableUsbPermissionDialogs);
|
||||||
|
|
||||||
mPermissionsFile = new AtomicFile(new File(
|
mPermissionsFile = new AtomicFile(new File(
|
||||||
Environment.getUserSystemDirectory(mUser.getIdentifier()),
|
Environment.getUserSystemDirectory(mUser.getIdentifier()),
|
||||||
"usb_permissions.xml"), "usb-permissions");
|
"usb_permissions.xml"), "usb-permissions");
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
readPermissionsLocked();
|
readPermissionsLocked();
|
||||||
}
|
}
|
||||||
@@ -195,11 +195,27 @@ class UsbUserPermissionManager {
|
|||||||
*/
|
*/
|
||||||
boolean hasPermission(@NonNull UsbDevice device, @NonNull String packageName, int pid,
|
boolean hasPermission(@NonNull UsbDevice device, @NonNull String packageName, int pid,
|
||||||
int uid) {
|
int uid) {
|
||||||
if (isCameraDevicePresent(device)) {
|
if (device.getHasVideoCapture()) {
|
||||||
if (!isCameraPermissionGranted(packageName, pid, uid)) {
|
boolean isCameraPrivacyEnabled = mSensorPrivacyMgrInternal.isSensorPrivacyEnabled(
|
||||||
|
UserHandle.getUserId(uid), Sensors.CAMERA);
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "isCameraPrivacyEnabled: " + isCameraPrivacyEnabled);
|
||||||
|
}
|
||||||
|
if (isCameraPrivacyEnabled || !isCameraPermissionGranted(packageName, pid, uid)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Only check for microphone privacy and not RECORD_AUDIO permission, because access to usb
|
||||||
|
// camera device with audio recording capabilities may still be granted with a warning
|
||||||
|
if (device.getHasAudioCapture() && mSensorPrivacyMgrInternal.isSensorPrivacyEnabled(
|
||||||
|
UserHandle.getUserId(uid), Sensors.MICROPHONE)) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG,
|
||||||
|
"Access to device with audio recording capabilities denied because "
|
||||||
|
+ "microphone privacy is enabled.");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
|
if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
|
||||||
return true;
|
return true;
|
||||||
@@ -698,7 +714,10 @@ class UsbUserPermissionManager {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isCameraDevicePresent(device)) {
|
// If the app doesn't have camera permission do not request permission to the USB device.
|
||||||
|
// Note that if the USB camera also has a microphone, a warning will be shown to the user if
|
||||||
|
// the app doesn't have RECORD_AUDIO permission.
|
||||||
|
if (device.getHasVideoCapture()) {
|
||||||
if (!isCameraPermissionGranted(packageName, pid, uid)) {
|
if (!isCameraPermissionGranted(packageName, pid, uid)) {
|
||||||
intent.putExtra(UsbManager.EXTRA_DEVICE, device);
|
intent.putExtra(UsbManager.EXTRA_DEVICE, device);
|
||||||
intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false);
|
intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false);
|
||||||
@@ -733,27 +752,4 @@ class UsbUserPermissionManager {
|
|||||||
requestPermissionDialog(null, accessory,
|
requestPermissionDialog(null, accessory,
|
||||||
mUsbUserSettingsManager.canBeDefault(accessory, packageName), packageName, pi, uid);
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user