Disallow usb access to camera and mic devices if global privacy toggle is active
Note that this will not prevent currently running apps from accessing usb devies to which a connection has already been established. Removed isCameraDevicePresent() as this has been implemented as well in UsbDevice#getHasVideoCapture(). Bug: 189915399 Test: Install nExt Camera - USB app, verify that camera is not accessible when camera privacy toggle is disabled. Change-Id: Ie60adfe9fc667d883ad4a6b8d7582a4bc17d1549
This commit is contained in:
@@ -25,12 +25,12 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.hardware.SensorPrivacyManager.Sensors;
|
||||
import android.hardware.SensorPrivacyManagerInternal;
|
||||
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.AsyncTask;
|
||||
import android.os.Binder;
|
||||
@@ -52,9 +52,9 @@ import android.util.TypedXmlSerializer;
|
||||
import android.util.Xml;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.internal.util.XmlUtils;
|
||||
import com.android.internal.util.dump.DualDumpOutputStream;
|
||||
import com.android.server.LocalServices;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
@@ -64,7 +64,6 @@ import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* UsbUserPermissionManager manages usb device or accessory access permissions.
|
||||
@@ -110,19 +109,20 @@ class UsbUserPermissionManager {
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private boolean mIsCopyPermissionsScheduled;
|
||||
private final SensorPrivacyManagerInternal mSensorPrivacyMgrInternal;
|
||||
|
||||
UsbUserPermissionManager(@NonNull Context context,
|
||||
@NonNull UsbUserSettingsManager usbUserSettingsManager) {
|
||||
mContext = context;
|
||||
mUser = context.getUser();
|
||||
mUsbUserSettingsManager = usbUserSettingsManager;
|
||||
mSensorPrivacyMgrInternal = LocalServices.getService(SensorPrivacyManagerInternal.class);
|
||||
mDisablePermissionDialogs = context.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_disableUsbPermissionDialogs);
|
||||
|
||||
mPermissionsFile = new AtomicFile(new File(
|
||||
Environment.getUserSystemDirectory(mUser.getIdentifier()),
|
||||
"usb_permissions.xml"), "usb-permissions");
|
||||
|
||||
synchronized (mLock) {
|
||||
readPermissionsLocked();
|
||||
}
|
||||
@@ -195,11 +195,27 @@ class UsbUserPermissionManager {
|
||||
*/
|
||||
boolean hasPermission(@NonNull UsbDevice device, @NonNull String packageName, int pid,
|
||||
int uid) {
|
||||
if (isCameraDevicePresent(device)) {
|
||||
if (!isCameraPermissionGranted(packageName, pid, uid)) {
|
||||
if (device.getHasVideoCapture()) {
|
||||
boolean isCameraPrivacyEnabled = mSensorPrivacyMgrInternal.isSensorPrivacyEnabled(
|
||||
UserHandle.getUserId(uid), Sensors.CAMERA);
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "isCameraPrivacyEnabled: " + isCameraPrivacyEnabled);
|
||||
}
|
||||
if (isCameraPrivacyEnabled || !isCameraPermissionGranted(packageName, pid, uid)) {
|
||||
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) {
|
||||
if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
|
||||
return true;
|
||||
@@ -698,7 +714,10 @@ class UsbUserPermissionManager {
|
||||
}
|
||||
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)) {
|
||||
intent.putExtra(UsbManager.EXTRA_DEVICE, device);
|
||||
intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false);
|
||||
@@ -733,27 +752,4 @@ class UsbUserPermissionManager {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user