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

Commit 5adfd4a5 authored by Yuting Fang's avatar Yuting Fang Committed by Android (Google) Code Review
Browse files

Merge "Always check device policy for device aware permission check and AppOp...

Merge "Always check device policy for device aware permission check and AppOp mode checking" into main
parents 124090d5 e16039df
Loading
Loading
Loading
Loading
+4 −41
Original line number Diff line number Diff line
@@ -22,14 +22,12 @@ import static android.os.StrictMode.vmIncorrectContextUseEnabled;
import static android.permission.flags.Flags.shouldRegisterAttributionSource;
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;
@@ -2367,47 +2365,11 @@ class ContextImpl extends Context {
            Log.v(TAG, "Treating renounced permission " + permission + " as denied");
            return PERMISSION_DENIED;
        }
        int deviceId = resolveDeviceIdForPermissionCheck(permission);
        int deviceId = PermissionManager.resolveDeviceIdForPermissionCheck(this, getDeviceId(),
                permission);
        return PermissionManager.checkPermission(permission, pid, uid, deviceId);
    }

    private int resolveDeviceIdForPermissionCheck(String permission) {
        // 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);
            if (virtualDeviceManager == null) {
                Slog.e(
                        TAG,
                        "VDM is not enabled when device id is not default. deviceId = "
                                + deviceId);
            } else {
                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 deviceId;
    }

    /** @hide */
    @Override
    public int checkPermission(String permission, int pid, int uid, IBinder callerToken) {
@@ -2511,7 +2473,8 @@ class ContextImpl extends Context {
    @Override
    public int getPermissionRequestState(String permission) {
        Objects.requireNonNull(permission, "Permission name can't be null");
        int deviceId = resolveDeviceIdForPermissionCheck(permission);
        int deviceId = PermissionManager.resolveDeviceIdForPermissionCheck(this, getDeviceId(),
                permission);
        PermissionManager permissionManager = getSystemService(PermissionManager.class);
        return permissionManager.getPermissionRequestState(getOpPackageName(), permission,
                deviceId);
+39 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.permission;

import static android.companion.virtual.VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE;
import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
@@ -2039,12 +2040,49 @@ public final class PermissionManager {
                new PackageNamePermissionQuery(permName, pkgName, persistentDeviceId, userId));
    }

    /**
     * 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.
     *
     * @hide
     */
    public static int resolveDeviceIdForPermissionCheck(@NonNull Context context, int deviceId,
            @Nullable String permission) {
        if (deviceId == Context.DEVICE_ID_DEFAULT || !DEVICE_AWARE_PERMISSIONS.contains(
                permission)) {
            return Context.DEVICE_ID_DEFAULT;
        }

        VirtualDeviceManager virtualDeviceManager =
                context.getSystemService(VirtualDeviceManager.class);
        if (virtualDeviceManager == null) {
            Slog.e(LOG_TAG, "VDM is not enabled when device id is not default. deviceId = "
                    + deviceId);
        } else {
            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(LOG_TAG,
                        "virtualDevice is not found when device id is not default. deviceId = "
                                + deviceId);
            }
        }
        return deviceId;
    }

    @Nullable
    private String getPersistentDeviceId(int deviceId) {
        String persistentDeviceId = null;

        if (deviceId == Context.DEVICE_ID_DEFAULT) {
            persistentDeviceId = VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT;
            persistentDeviceId = PERSISTENT_DEVICE_ID_DEFAULT;
        } else {
            VirtualDeviceManager virtualDeviceManager = mContext.getSystemService(
                    VirtualDeviceManager.class);
+31 −18
Original line number Diff line number Diff line
@@ -3006,7 +3006,7 @@ public class AppOpsService extends IAppOpsService.Stub {
            UidState uidState = getUidStateLocked(uid, false);
            if (uidState != null) {
                int rawUidMode = mAppOpsCheckingService.getUidMode(
                        uidState.uid, getPersistentId(virtualDeviceId), code);
                        uidState.uid, getPersistentDeviceIdForOp(virtualDeviceId, code), code);

                if (rawUidMode != AppOpsManager.opToDefaultMode(code)) {
                    return raw ? rawUidMode :
@@ -3069,7 +3069,7 @@ public class AppOpsService extends IAppOpsService.Stub {

            int switchCode = AppOpsManager.opToSwitch(code);
            int rawUidMode = mAppOpsCheckingService.getUidMode(uid,
                    getPersistentId(virtualDeviceId), switchCode);
                    getPersistentDeviceIdForOp(virtualDeviceId, switchCode), switchCode);

            if (rawUidMode != AppOpsManager.opToDefaultMode(switchCode)) {
                return raw ? rawUidMode : evaluateForegroundMode(uid, switchCode, rawUidMode);
@@ -3396,7 +3396,7 @@ public class AppOpsService extends IAppOpsService.Stub {
            }
            final Op op = getOpLocked(ops, code, uid, true);
            final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag,
                    getPersistentId(virtualDeviceId));
                    getPersistentDeviceIdForOp(virtualDeviceId, code));
            if (attributedOp.isRunning()) {
                Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName + " code "
                        + code + " startTime of in progress event="
@@ -3418,15 +3418,15 @@ public class AppOpsService extends IAppOpsService.Stub {

                // If there is a non-default per UID policy (we set UID op mode only if
                // non-default) it takes over, otherwise use the per package policy.
            } else if (mAppOpsCheckingService.getUidMode(
                            uidState.uid, getPersistentId(virtualDeviceId), switchCode)
            } else if (mAppOpsCheckingService.getUidMode(uidState.uid,
                    getPersistentDeviceIdForOp(virtualDeviceId, switchCode), switchCode)
                    != AppOpsManager.opToDefaultMode(switchCode)) {
                final int uidMode =
                        uidState.evalMode(
                                code,
                                mAppOpsCheckingService.getUidMode(
                                        uidState.uid,
                                        getPersistentId(virtualDeviceId),
                                        getPersistentDeviceIdForOp(virtualDeviceId, switchCode),
                                        switchCode));
                if (uidMode != AppOpsManager.MODE_ALLOWED) {
                    if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
@@ -3478,7 +3478,8 @@ public class AppOpsService extends IAppOpsService.Stub {
                    virtualDeviceId, flags, AppOpsManager.MODE_ALLOWED);

            attributedOp.accessed(proxyUid, proxyPackageName, proxyAttributionTag,
                    getPersistentId(proxyVirtualDeviceId), uidState.getState(), flags, notedCount);
                    getPersistentDeviceIdForOp(proxyVirtualDeviceId, code), uidState.getState(),
                    flags, notedCount);

            if (shouldCollectAsyncNotedOp) {
                collectAsyncNotedOp(uid, packageName, code, attributionTag, flags, message,
@@ -4045,7 +4046,7 @@ public class AppOpsService extends IAppOpsService.Stub {
            }
            final Op op = getOpLocked(ops, code, uid, true);
            final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag,
                    getPersistentId(virtualDeviceId));
                    getPersistentDeviceIdForOp(virtualDeviceId, code));
            final UidState uidState = ops.uidState;
            isRestricted = isOpRestrictedLocked(uid, code, packageName, attributionTag,
                    virtualDeviceId, pvr.bypass, false);
@@ -4059,7 +4060,8 @@ public class AppOpsService extends IAppOpsService.Stub {
                // non-default) it takes over, otherwise use the per package policy.
            } else if ((rawUidMode =
                    mAppOpsCheckingService.getUidMode(
                                    uidState.uid, getPersistentId(virtualDeviceId), switchCode))
                            uidState.uid, getPersistentDeviceIdForOp(virtualDeviceId, switchCode),
                            switchCode))
                    != AppOpsManager.opToDefaultMode(switchCode)) {
                final int uidMode = uidState.evalMode(code, rawUidMode);
                if (!shouldStartForMode(uidMode, startIfModeDefault)) {
@@ -4107,11 +4109,13 @@ public class AppOpsService extends IAppOpsService.Stub {
            try {
                if (isRestricted) {
                    attributedOp.createPaused(clientId, virtualDeviceId, proxyUid, proxyPackageName,
                            proxyAttributionTag, getPersistentId(proxyVirtualDeviceId),
                            proxyAttributionTag,
                            getPersistentDeviceIdForOp(proxyVirtualDeviceId, code),
                            uidState.getState(), flags, attributionFlags, attributionChainId);
                } else {
                    attributedOp.started(clientId, virtualDeviceId, proxyUid, proxyPackageName,
                            proxyAttributionTag, getPersistentId(proxyVirtualDeviceId),
                            proxyAttributionTag,
                            getPersistentDeviceIdForOp(proxyVirtualDeviceId, code),
                            uidState.getState(), flags, attributionFlags, attributionChainId);
                    startType = START_TYPE_STARTED;
                }
@@ -4179,15 +4183,15 @@ public class AppOpsService extends IAppOpsService.Stub {
            final int switchCode = AppOpsManager.opToSwitch(code);
            // If there is a non-default mode per UID policy (we set UID op mode only if
            // non-default) it takes over, otherwise use the per package policy.
            if (mAppOpsCheckingService.getUidMode(
                            uidState.uid, getPersistentId(virtualDeviceId), switchCode)
            if (mAppOpsCheckingService.getUidMode(uidState.uid,
                    getPersistentDeviceIdForOp(virtualDeviceId, switchCode), switchCode)
                    != AppOpsManager.opToDefaultMode(switchCode)) {
                final int uidMode =
                        uidState.evalMode(
                                code,
                                mAppOpsCheckingService.getUidMode(
                                        uidState.uid,
                                        getPersistentId(virtualDeviceId),
                                        getPersistentDeviceIdForOp(virtualDeviceId, switchCode),
                                        switchCode));
                if (!shouldStartForMode(uidMode, startIfModeDefault)) {
                    if (DEBUG) {
@@ -4350,7 +4354,8 @@ public class AppOpsService extends IAppOpsService.Stub {
                return;
            }
            final AttributedOp attributedOp =
                    op.mDeviceAttributedOps.getOrDefault(getPersistentId(virtualDeviceId),
                    op.mDeviceAttributedOps.getOrDefault(
                            getPersistentDeviceIdForOp(virtualDeviceId, code),
                            new ArrayMap<>()).get(attributionTag);
            if (attributedOp == null) {
                Slog.e(TAG, "Attribution not found: uid=" + uid + " pkg=" + packageName + "("
@@ -4641,7 +4646,8 @@ public class AppOpsService extends IAppOpsService.Stub {
            return true;
        }
        if (mVirtualDeviceManagerInternal == null) {
            return true;
            Slog.w(TAG, "VirtualDeviceManagerInternal is null when device Id is non-default");
            return false;
        }
        if (mVirtualDeviceManagerInternal.isValidVirtualDeviceId(virtualDeviceId)) {
            mKnownDeviceIds.put(virtualDeviceId,
@@ -7310,7 +7316,13 @@ public class AppOpsService extends IAppOpsService.Stub {
        return packageNames;
    }

    @NonNull private String getPersistentId(int virtualDeviceId) {
    // For ops associated with device aware permissions, if virtual device id is non-default, we
    // will return string version of that id provided the virtual device has corresponding camera or
    // audio policy.
    @NonNull private String getPersistentDeviceIdForOp(int virtualDeviceId, int op) {
        virtualDeviceId = PermissionManager.resolveDeviceIdForPermissionCheck(mContext,
                virtualDeviceId, AppOpsManager.opToPermission(op));

        if (virtualDeviceId == Context.DEVICE_ID_DEFAULT) {
            return PERSISTENT_DEVICE_ID_DEFAULT;
        }
@@ -7319,6 +7331,7 @@ public class AppOpsService extends IAppOpsService.Stub {
        }
        String persistentId =
                mVirtualDeviceManagerInternal.getPersistentIdForDevice(virtualDeviceId);

        if (persistentId == null) {
            persistentId = mKnownDeviceIds.get(virtualDeviceId);
        }