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

Commit 3c6a28b9 authored by Yuting's avatar Yuting
Browse files

Perform device capability check when checking device aware permission on

remote devices

When checking CAMERA or RECORD_AUDIO permissions on a remote device,
perform corresponding device capability check. If the remote device
doesn't have such capability fall back the permission check to the default
device so the camera/recorder on the default device can be used if
permission is granted.

Bug: 331165303
Test: atest VirtualAudioPermissionTest
Change-Id: If205eee8bcb9adcf474aef7f0ee35b4cc22e7ab3
parent fbc3ba8b
Loading
Loading
Loading
Loading
+31 −1
Original line number Diff line number Diff line
@@ -21,12 +21,14 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.StrictMode.vmIncorrectContextUseEnabled;
import static android.view.WindowManager.LayoutParams.WindowType;

import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.UiContext;
import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.AttributionSource;
@@ -2288,7 +2290,35 @@ class ContextImpl extends Context {
            Log.v(TAG, "Treating renounced permission " + permission + " as denied");
            return PERMISSION_DENIED;
        }
        return PermissionManager.checkPermission(permission, pid, uid, getDeviceId());

        // When checking a device-aware permission on a remote device, if the permission is CAMERA
        // or RECORD_AUDIO we need to check remote device's corresponding capability. If the remote
        // device doesn't have capability fall back to checking permission on the default device.
        // Note: we only perform permission check redirection when the device id is not explicitly
        // set in the context.
        int deviceId = getDeviceId();
        if (deviceId != Context.DEVICE_ID_DEFAULT
                && !mIsExplicitDeviceId
                && PermissionManager.DEVICE_AWARE_PERMISSIONS.contains(permission)) {
            VirtualDeviceManager virtualDeviceManager =
                    getSystemService(VirtualDeviceManager.class);
            VirtualDevice virtualDevice = virtualDeviceManager.getVirtualDevice(deviceId);
            if (virtualDevice != null) {
                if ((Objects.equals(permission, Manifest.permission.RECORD_AUDIO)
                                && !virtualDevice.hasCustomAudioInputSupport())
                        || (Objects.equals(permission, Manifest.permission.CAMERA)
                                && !virtualDevice.hasCustomCameraSupport())) {
                    deviceId = Context.DEVICE_ID_DEFAULT;
                }
            } else {
                Slog.e(
                        TAG,
                        "virtualDevice is not found when device id is not default. deviceId = "
                                + deviceId);
            }
        }

        return PermissionManager.checkPermission(permission, pid, uid, deviceId);
    }

    /** @hide */
+10 −0
Original line number Diff line number Diff line
@@ -240,6 +240,16 @@ public final class PermissionManager {
    public static final String EXTRA_PERMISSION_USAGES =
            "android.permission.extra.PERMISSION_USAGES";

    /**
     * Specify what permissions are device aware. Only device aware permissions can be granted to
     * a remote device.
     * @hide
     */
    public static final Set<String> DEVICE_AWARE_PERMISSIONS =
            Flags.deviceAwarePermissionsEnabled()
                    ? Set.of(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
                    : Collections.emptySet();

    private final @NonNull Context mContext;

    private final IPackageManager mPackageManager;
+2 −11
Original line number Diff line number Diff line
@@ -1598,7 +1598,7 @@ class PermissionService(private val service: AccessCheckingService) :
        ) {
            with(policy) { getPermissionFlags(appId, userId, permissionName) }
        } else {
            if (permissionName !in DEVICE_AWARE_PERMISSIONS) {
            if (permissionName !in PermissionManager.DEVICE_AWARE_PERMISSIONS) {
                Slog.i(
                    LOG_TAG,
                    "$permissionName is not device aware permission, " +
@@ -1623,7 +1623,7 @@ class PermissionService(private val service: AccessCheckingService) :
        ) {
            with(policy) { setPermissionFlags(appId, userId, permissionName, flags) }
        } else {
            if (permissionName !in DEVICE_AWARE_PERMISSIONS) {
            if (permissionName !in PermissionManager.DEVICE_AWARE_PERMISSIONS) {
                Slog.i(
                    LOG_TAG,
                    "$permissionName is not device aware permission, " +
@@ -2820,15 +2820,6 @@ class PermissionService(private val service: AccessCheckingService) :
                PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM or
                PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER

        /** These permissions are supported for virtual devices. */
        // TODO: b/298661870 - Use new API to get the list of device aware permissions.
        val DEVICE_AWARE_PERMISSIONS =
            if (Flags.deviceAwarePermissionsEnabled()) {
                setOf(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
            } else {
                emptySet<String>()
            }

        fun getFullerPermission(permissionName: String): String? =
            FULLER_PERMISSIONS[permissionName]
    }