Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b6c805e authored by Philip Junker's avatar Philip Junker Committed by Automerger Merge Worker
Browse files

Merge "Disallow usb access to camera and mic devices if global privacy toggle...

Merge "Disallow usb access to camera and mic devices if global privacy toggle is active" into sc-dev am: c20398b8

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15462072

Change-Id: I3209ca3dafcaf47426bffa08c4da47a8a6667286
parents 9100f2f0 c20398b8
Loading
Loading
Loading
Loading
+27 −31
Original line number Diff line number Diff line
@@ -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;
    }
}