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

Commit 781c51ac authored by Yuting Fang's avatar Yuting Fang
Browse files

Create a system API to check permission by persistent device Id

The new system Api in PermissionManager is used to check permission against a persistent device Id. It uses the
same cache sPackageNamePermissionCache as the one used by PackageManager#checkPermission, but changes the cache to use
persistentDeviceId in the cache key instead of VDID.

Bug: b/315356442
Test: ag/26168815 atest DevicePermissionsTest
Change-Id: I6043229a70b30b71652466fed07fd151aff8883c
parent a84693ee
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -11276,6 +11276,7 @@ package android.permission {
  public final class PermissionManager {
    method public int checkDeviceIdentifierAccess(@Nullable String, @Nullable String, @Nullable String, int, int);
    method @FlaggedApi("android.permission.flags.device_aware_permission_apis_enabled") public static int checkPermission(@NonNull String, @NonNull String, @NonNull String, int);
    method @RequiresPermission(value=android.Manifest.permission.UPDATE_APP_OPS_STATS, conditional=true) public int checkPermissionForDataDelivery(@NonNull String, @NonNull android.content.AttributionSource, @Nullable String);
    method @RequiresPermission(value=android.Manifest.permission.UPDATE_APP_OPS_STATS, conditional=true) public int checkPermissionForDataDeliveryFromDataSource(@NonNull String, @NonNull android.content.AttributionSource, @Nullable String);
    method public int checkPermissionForPreflight(@NonNull String, @NonNull android.content.AttributionSource);
+1 −1
Original line number Diff line number Diff line
@@ -836,7 +836,7 @@ public class ApplicationPackageManager extends PackageManager {

    @Override
    public int checkPermission(String permName, String pkgName) {
        return PermissionManager.checkPackageNamePermission(permName, pkgName,
        return getPermissionManager().checkPackageNamePermission(permName, pkgName,
                mContext.getDeviceId(), getUserId());
    }

+2 −1
Original line number Diff line number Diff line
@@ -96,7 +96,8 @@ interface IPermissionManager {

    boolean isRegisteredAttributionSource(in AttributionSourceState source);

    int checkPermission(String packageName, String permissionName, int deviceId, int userId);
    int checkPermission(String packageName, String permissionName, String persistentDeviceId,
            int userId);

    int checkUidPermission(int uid, String permissionName, int deviceId);
}
+75 −13
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import static android.permission.flags.Flags.serverSideAttributionRegistration;
import android.Manifest;
import android.annotation.CheckResult;
import android.annotation.DurationMillisLong;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
@@ -45,6 +46,8 @@ import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.PropertyInvalidatedCache;
import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceManager;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.content.AttributionSource;
@@ -68,6 +71,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.permission.flags.Flags;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -240,6 +244,8 @@ public final class PermissionManager {

    private final LegacyPermissionManager mLegacyPermissionManager;

    private final VirtualDeviceManager mVirtualDeviceManager;

    private final ArrayMap<PackageManager.OnPermissionsChangedListener,
            IOnPermissionsChangeListener> mPermissionListeners = new ArrayMap<>();
    private PermissionUsageHelper mUsageHelper;
@@ -260,6 +266,7 @@ public final class PermissionManager {
        mPermissionManager = IPermissionManager.Stub.asInterface(ServiceManager.getServiceOrThrow(
                "permissionmgr"));
        mLegacyPermissionManager = context.getSystemService(LegacyPermissionManager.class);
        mVirtualDeviceManager = context.getSystemService(VirtualDeviceManager.class);
    }

    /**
@@ -1642,15 +1649,15 @@ public final class PermissionManager {
    private static final class PackageNamePermissionQuery {
        final String permName;
        final String pkgName;
        final int deviceId;
        final String persistentDeviceId;
        @UserIdInt
        final int userId;

        PackageNamePermissionQuery(@Nullable String permName, @Nullable String pkgName,
                int deviceId, @UserIdInt int userId) {
                @Nullable String persistentDeviceId, @UserIdInt int userId) {
            this.permName = permName;
            this.pkgName = pkgName;
            this.deviceId = deviceId;
            this.persistentDeviceId = persistentDeviceId;
            this.userId = userId;
        }

@@ -1658,13 +1665,13 @@ public final class PermissionManager {
        public String toString() {
            return TextUtils.formatSimple(
                    "PackageNamePermissionQuery(pkgName=\"%s\", permName=\"%s\", "
                            + "deviceId=%s, userId=%s\")",
                    pkgName, permName, deviceId, userId);
                            + "persistentDeviceId=%s, userId=%s\")",
                    pkgName, permName, persistentDeviceId, userId);
        }

        @Override
        public int hashCode() {
            return Objects.hash(permName, pkgName, deviceId, userId);
            return Objects.hash(permName, pkgName, persistentDeviceId, userId);
        }

        @Override
@@ -1680,17 +1687,17 @@ public final class PermissionManager {
            }
            return Objects.equals(permName, other.permName)
                    && Objects.equals(pkgName, other.pkgName)
                    && deviceId == other.deviceId
                    && Objects.equals(persistentDeviceId, other.persistentDeviceId)
                    && userId == other.userId;
        }
    }

    /* @hide */
    private static int checkPackageNamePermissionUncached(
            String permName, String pkgName, int deviceId, @UserIdInt int userId) {
            String permName, String pkgName, String persistentDeviceId, @UserIdInt int userId) {
        try {
            return ActivityThread.getPermissionManager().checkPermission(
                    pkgName, permName, deviceId, userId);
                    pkgName, permName, persistentDeviceId, userId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -1704,7 +1711,7 @@ public final class PermissionManager {
                @Override
                public Integer recompute(PackageNamePermissionQuery query) {
                    return checkPackageNamePermissionUncached(
                            query.permName, query.pkgName, query.deviceId, query.userId);
                            query.permName, query.pkgName, query.persistentDeviceId, query.userId);
                }
                @Override
                public boolean bypass(PackageNamePermissionQuery query) {
@@ -1717,10 +1724,65 @@ public final class PermissionManager {
     *
     * @hide
     */
    public static int checkPackageNamePermission(String permName, String pkgName, int deviceId,
            @UserIdInt int userId) {
    public int checkPackageNamePermission(String permName, String pkgName,
            int deviceId, @UserIdInt int userId) {
        String persistentDeviceId = getPersistentDeviceId(deviceId);
        return sPackageNamePermissionCache.query(
                new PackageNamePermissionQuery(permName, pkgName, persistentDeviceId, userId));
    }

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

        if (deviceId == Context.DEVICE_ID_DEFAULT) {
            persistentDeviceId = VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT;
        } else if (android.companion.virtual.flags.Flags.vdmPublicApis()) {
            VirtualDevice virtualDevice = mVirtualDeviceManager.getVirtualDevice(deviceId);
            if (virtualDevice == null) {
                Slog.e(LOG_TAG, "Virtual device is not found with device Id " + deviceId);
                return null;
            }
            persistentDeviceId = virtualDevice.getPersistentDeviceId();
            if (persistentDeviceId == null) {
                Slog.e(LOG_TAG, "Cannot find persistent device Id for " + deviceId);
            }
        } else {
            Slog.e(LOG_TAG, "vdmPublicApis flag is not enabled when device Id " + deviceId
                    + "is not default.");
        }
        return persistentDeviceId;
    }

    /**
     * Check whether a package has been granted a permission on a given device.
     * <p>
     * <strong>Note: </strong>This API returns the underlying permission state
     * as-is and is mostly intended for permission managing system apps. To
     * perform an access check for a certain app, please use the
     * {@link Context#checkPermission} APIs instead.
     *
     * @param permissionName The name of the permission you are checking for.
     * @param packageName The name of the package you are checking against.
     * @param persistentDeviceId The persistent device id you are checking against.
     * @param userId The user Id associated with context.
     *
     * @return If the package has the permission on the device, PERMISSION_GRANTED is
     * returned.  If it does not have the permission on the device, PERMISSION_DENIED
     * is returned.
     *
     * @see PackageManager#PERMISSION_GRANTED
     * @see PackageManager#PERMISSION_DENIED
     *
     * @hide
     */
    @SystemApi
    @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
    public static int checkPermission(@NonNull String permissionName, @NonNull String packageName,
            @NonNull String persistentDeviceId, @UserIdInt int userId) {
        return sPackageNamePermissionCache.query(
                new PackageNamePermissionQuery(permName, pkgName, deviceId, userId));
                new PackageNamePermissionQuery(permissionName, packageName, persistentDeviceId,
                        userId));
    }

    /**
+3 −2
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.annotation.RequiresPermission;
import android.app.Flags;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
import android.companion.virtual.VirtualDeviceManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.IBackgroundInstallControlService;
@@ -257,7 +258,7 @@ public class BackgroundInstallControlService extends SystemService {
        if (mPermissionManager.checkPermission(
                installerPackageName,
                android.Manifest.permission.INSTALL_PACKAGES,
                Context.DEVICE_ID_DEFAULT,
                VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT,
                userId)
                != PERMISSION_GRANTED) {
            return;
@@ -464,7 +465,7 @@ public class BackgroundInstallControlService extends SystemService {
        return mPermissionManager.checkPermission(
                pkgName,
                android.Manifest.permission.INSTALL_PACKAGES,
                Context.DEVICE_ID_DEFAULT,
                VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT,
                userId)
                == PERMISSION_GRANTED;
    }
Loading