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
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 515d017..b55a39d 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -11276,6 +11276,7 @@
 
   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);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index d8aded40..3ec39b5 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -836,7 +836,7 @@
 
     @Override
     public int checkPermission(String permName, String pkgName) {
-        return PermissionManager.checkPackageNamePermission(permName, pkgName,
+        return getPermissionManager().checkPackageNamePermission(permName, pkgName,
                 mContext.getDeviceId(), getUserId());
     }
 
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 471f95b..49e0634 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -96,7 +96,8 @@
 
     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);
 }
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 4af6e3a..cb71ec0 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -28,6 +28,7 @@
 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.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.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 @@
 
     private final LegacyPermissionManager mLegacyPermissionManager;
 
+    private final VirtualDeviceManager mVirtualDeviceManager;
+
     private final ArrayMap<PackageManager.OnPermissionsChangedListener,
             IOnPermissionsChangeListener> mPermissionListeners = new ArrayMap<>();
     private PermissionUsageHelper mUsageHelper;
@@ -260,6 +266,7 @@
         mPermissionManager = IPermissionManager.Stub.asInterface(ServiceManager.getServiceOrThrow(
                 "permissionmgr"));
         mLegacyPermissionManager = context.getSystemService(LegacyPermissionManager.class);
+        mVirtualDeviceManager = context.getSystemService(VirtualDeviceManager.class);
     }
 
     /**
@@ -1642,15 +1649,15 @@
     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 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 @@
             }
             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 @@
                 @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 @@
      *
      * @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, deviceId, userId));
+                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(permissionName, packageName, persistentDeviceId,
+                        userId));
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
index 200b17b..931fe29 100644
--- a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
+++ b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
@@ -24,6 +24,7 @@
 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 @@
         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 @@
         return mPermissionManager.checkPermission(
                 pkgName,
                 android.Manifest.permission.INSTALL_PACKAGES,
-                Context.DEVICE_ID_DEFAULT,
+                VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT,
                 userId)
                 == PERMISSION_GRANTED;
     }
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index ac89fecc..9afdde5 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -69,6 +69,7 @@
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.admin.DevicePolicyManagerInternal;
+import android.companion.virtual.VirtualDeviceManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -4615,7 +4616,8 @@
         for (int i=0; i<permissions.length; i++) {
             final String permission = permissions[i];
             if (mPermissionManager.checkPermission(ps.getPackageName(), permission,
-                    Context.DEVICE_ID_DEFAULT, userId) == PERMISSION_GRANTED) {
+                    VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT, userId)
+                    == PERMISSION_GRANTED) {
                 tmp[i] = true;
                 numMatch++;
             } else {
diff --git a/services/core/java/com/android/server/pm/DumpHelper.java b/services/core/java/com/android/server/pm/DumpHelper.java
index 2a00a44..104e8be 100644
--- a/services/core/java/com/android/server/pm/DumpHelper.java
+++ b/services/core/java/com/android/server/pm/DumpHelper.java
@@ -22,8 +22,8 @@
 import static com.android.server.pm.PackageManagerServiceUtils.dumpCriticalInfo;
 
 import android.annotation.NonNull;
+import android.companion.virtual.VirtualDeviceManager;
 import android.content.ComponentName;
-import android.content.Context;
 import android.content.pm.FeatureInfo;
 import android.content.pm.PackageManager;
 import android.os.Binder;
@@ -162,7 +162,7 @@
                         PackageManager.VERSION_CODE_HIGHEST);
 
                 pw.println(mPermissionManager.checkPermission(
-                        pkg, perm, Context.DEVICE_ID_DEFAULT, user));
+                        pkg, perm, VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT, user));
                 return;
             } else if ("l".equals(cmd) || "libraries".equals(cmd)) {
                 dumpState.setDump(DumpState.DUMP_LIBS);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b8960da..83dd0e8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -65,6 +65,7 @@
 import android.app.admin.SecurityLog;
 import android.app.backup.IBackupManager;
 import android.app.role.RoleManager;
+import android.companion.virtual.VirtualDeviceManager;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledAfter;
 import android.content.BroadcastReceiver;
@@ -2993,8 +2994,8 @@
 
     // NOTE: Can't remove due to unsupported app usage
     public int checkPermission(String permName, String pkgName, int userId) {
-        return mPermissionManager.checkPermission(pkgName, permName, Context.DEVICE_ID_DEFAULT,
-                userId);
+        return mPermissionManager.checkPermission(pkgName, permName,
+                VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT, userId);
     }
 
     public String getSdkSandboxPackageName() {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 40f2264..240e37e 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -217,7 +217,7 @@
 
     @Override
     @PackageManager.PermissionResult
-    public int checkPermission(String packageName, String permissionName, int deviceId,
+    public int checkPermission(String packageName, String permissionName, String persistentDeviceId,
             @UserIdInt int userId) {
         // Not using Objects.requireNonNull() here for compatibility reasons.
         if (packageName == null || permissionName == null) {
@@ -231,10 +231,10 @@
 
         if (checkPermissionDelegate == null) {
             return mPermissionManagerServiceImpl.checkPermission(packageName, permissionName,
-                    deviceId, userId);
+                    persistentDeviceId, userId);
         }
         return checkPermissionDelegate.checkPermission(packageName, permissionName,
-                deviceId, userId, mPermissionManagerServiceImpl::checkPermission);
+                persistentDeviceId, userId, mPermissionManagerServiceImpl::checkPermission);
     }
 
     @Override
@@ -620,9 +620,9 @@
     private class PermissionManagerServiceInternalImpl implements PermissionManagerServiceInternal {
         @Override
         public int checkPermission(@NonNull String packageName, @NonNull String permissionName,
-                int deviceId, @UserIdInt int userId) {
+                @NonNull String persistentDeviceId, @UserIdInt int userId) {
             return PermissionManagerService.this.checkPermission(packageName, permissionName,
-                    deviceId, userId);
+                    persistentDeviceId, userId);
         }
 
         @Override
@@ -888,7 +888,7 @@
          *
          * @param packageName the name of the package to be checked
          * @param permissionName the name of the permission to be checked
-         * @param deviceId The device ID
+         * @param persistentDeviceId The persistent device ID
          * @param userId the user ID
          * @param superImpl the original implementation that can be delegated to
          * @return {@link android.content.pm.PackageManager#PERMISSION_GRANTED} if the package has
@@ -897,8 +897,8 @@
          * @see android.content.pm.PackageManager#checkPermission(String, String)
          */
         int checkPermission(@NonNull String packageName, @NonNull String permissionName,
-                int deviceId, @UserIdInt int userId,
-                @NonNull QuadFunction<String, String, Integer, Integer, Integer> superImpl);
+                String persistentDeviceId, @UserIdInt int userId,
+                @NonNull QuadFunction<String, String, String, Integer, Integer> superImpl);
 
         /**
          * Check whether the given UID has been granted the specified permission.
@@ -940,18 +940,19 @@
 
         @Override
         public int checkPermission(@NonNull String packageName, @NonNull String permissionName,
-                int deviceId, int userId,
-                @NonNull QuadFunction<String, String, Integer, Integer, Integer> superImpl) {
+                String persistentDeviceId, int userId,
+                @NonNull QuadFunction<String, String, String, Integer, Integer> superImpl) {
             if (mDelegatedPackageName.equals(packageName)
                     && isDelegatedPermission(permissionName)) {
                 final long identity = Binder.clearCallingIdentity();
                 try {
-                    return superImpl.apply("com.android.shell", permissionName, deviceId, userId);
+                    return superImpl.apply("com.android.shell", permissionName, persistentDeviceId,
+                            userId);
                 } finally {
                     Binder.restoreCallingIdentity(identity);
                 }
             }
-            return superImpl.apply(packageName, permissionName, deviceId, userId);
+            return superImpl.apply(packageName, permissionName, persistentDeviceId, userId);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 6a57362..c33f1eb 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -910,11 +910,13 @@
     }
 
     private int checkPermission(String pkgName, String permName, int userId) {
-        return checkPermission(pkgName, permName, Context.DEVICE_ID_DEFAULT, userId);
+        return checkPermission(pkgName, permName, VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT,
+                userId);
     }
 
     @Override
-    public int checkPermission(String pkgName, String permName, int deviceId, int userId) {
+    public int checkPermission(String pkgName, String permName, String persistentDeviceId,
+            int userId) {
         if (!mUserManagerInt.exists(userId)) {
             return PackageManager.PERMISSION_DENIED;
         }
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
index 2d824aa..d221515 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
@@ -387,11 +387,12 @@
      *
      * @param pkgName package name
      * @param permName permission name
-     * @param deviceId device ID
+     * @param persistentDeviceId  persistent device ID
      * @param userId user ID
      * @return permission result {@link PackageManager.PermissionResult}
      */
-    int checkPermission(String pkgName, String permName, int deviceId, @UserIdInt int userId);
+    int checkPermission(String pkgName, String permName, String persistentDeviceId,
+            @UserIdInt int userId);
 
     /**
      * Check whether a permission is granted or not to an UID.
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 98adeb6..132cdce 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -46,14 +46,14 @@
      *
      * @param packageName the name of the package you are checking against
      * @param permissionName the name of the permission you are checking for
-     * @param deviceId the device ID
+     * @param persistentDeviceId the persistent device ID to check permission for
      * @param userId the user ID
      * @return {@code PERMISSION_GRANTED} if the permission is granted, or {@code PERMISSION_DENIED}
      *         otherwise
      */
     //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
-    int checkPermission(@NonNull String packageName, @NonNull String permissionName, int deviceId,
-            @UserIdInt int userId);
+    int checkPermission(@NonNull String packageName, @NonNull String permissionName,
+            @NonNull String persistentDeviceId, @UserIdInt int userId);
 
     /**
      * Check whether a particular UID has been granted a particular permission.
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceLoggingDecorator.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceLoggingDecorator.java
index dacb8c6..e6e84f9 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceLoggingDecorator.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceLoggingDecorator.java
@@ -230,10 +230,11 @@
     }
 
     @Override
-    public int checkPermission(String pkgName, String permName, int deviceId, int userId) {
+    public int checkPermission(String pkgName, String permName, String persistentDeviceId,
+            int userId) {
         Log.i(LOG_TAG, "checkPermission(pkgName = " + pkgName + ", permName = " + permName
-                + ", deviceId = " + deviceId + ", userId = " + userId + ")");
-        return mService.checkPermission(pkgName, permName, deviceId, userId);
+                + ", persistentDeviceId = " + persistentDeviceId + ", userId = " + userId + ")");
+        return mService.checkPermission(pkgName, permName, persistentDeviceId, userId);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java
index 35d165b..36b2135 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java
@@ -296,9 +296,12 @@
     }
 
     @Override
-    public int checkPermission(String pkgName, String permName, int deviceId, int userId) {
-        int oldVal = mOldImplementation.checkPermission(pkgName, permName, deviceId, userId);
-        int newVal = mNewImplementation.checkPermission(pkgName, permName, deviceId, userId);
+    public int checkPermission(String pkgName, String permName, String persistentDeviceId,
+            int userId) {
+        int oldVal = mOldImplementation.checkPermission(pkgName, permName, persistentDeviceId,
+                userId);
+        int newVal = mNewImplementation.checkPermission(pkgName, permName, persistentDeviceId,
+                userId);
 
         if (!Objects.equals(oldVal, newVal)) {
             signalImplDifference("checkPermission");
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTracingDecorator.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTracingDecorator.java
index cbeede0..eafd907 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTracingDecorator.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTracingDecorator.java
@@ -324,10 +324,11 @@
     }
 
     @Override
-    public int checkPermission(String pkgName, String permName, int deviceId, int userId) {
+    public int checkPermission(String pkgName, String permName, String persistentDeviceId,
+            int userId) {
         Trace.traceBegin(TRACE_TAG, "TaggedTracingPermissionManagerServiceImpl#checkPermission");
         try {
-            return mService.checkPermission(pkgName, permName, deviceId, userId);
+            return mService.checkPermission(pkgName, permName, persistentDeviceId, userId);
         } finally {
             Trace.traceEnd(TRACE_TAG);
         }
diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
index 097d73a..7d8cbe6 100644
--- a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
@@ -423,6 +423,7 @@
             with(policy) { removePermission(permission) }
         }
     }
+
     private fun GetStateScope.getAndEnforcePermissionTree(permissionName: String): Permission {
         val callingUid = Binder.getCallingUid()
         val permissionTree = with(policy) { findPermissionTree(permissionName) }
@@ -486,9 +487,16 @@
                 )
                 return PackageManager.PERMISSION_DENIED
             }
+
+            val persistentDeviceId = getPersistentDeviceId(deviceId)
+            if (persistentDeviceId == null) {
+                Slog.e(LOG_TAG, "Cannot find persistent device id for $deviceId.")
+                return PackageManager.PERMISSION_DENIED
+            }
+
             val isPermissionGranted =
                 service.getState {
-                    isPermissionGranted(packageState, userId, permissionName, deviceId)
+                    isPermissionGranted(packageState, userId, permissionName, persistentDeviceId)
                 }
             return if (isPermissionGranted) {
                 PackageManager.PERMISSION_GRANTED
@@ -522,7 +530,7 @@
     override fun checkPermission(
         packageName: String,
         permissionName: String,
-        deviceId: Int,
+        persistentDeviceId: String,
         userId: Int
     ): Int {
         if (!userManagerInternal.exists(userId)) {
@@ -536,7 +544,9 @@
                 ?: return PackageManager.PERMISSION_DENIED
 
         val isPermissionGranted =
-            service.getState { isPermissionGranted(packageState, userId, permissionName, deviceId) }
+            service.getState {
+                isPermissionGranted(packageState, userId, permissionName, persistentDeviceId)
+            }
         return if (isPermissionGranted) {
             PackageManager.PERMISSION_GRANTED
         } else {
@@ -554,13 +564,21 @@
         packageState: PackageState,
         userId: Int,
         permissionName: String,
-        deviceId: Int
+        persistentDeviceId: String
     ): Boolean {
         val appId = packageState.appId
         // Note that instant apps can't have shared UIDs, so we only need to check the current
         // package state.
         val isInstantApp = packageState.getUserStateOrDefault(userId).isInstantApp
-        if (isSinglePermissionGranted(appId, userId, isInstantApp, permissionName, deviceId)) {
+        if (
+            isSinglePermissionGranted(
+                appId,
+                userId,
+                isInstantApp,
+                permissionName,
+                persistentDeviceId
+            )
+        ) {
             return true
         }
 
@@ -572,7 +590,7 @@
                     userId,
                     isInstantApp,
                     fullerPermissionName,
-                    deviceId
+                    persistentDeviceId
                 )
         ) {
             return true
@@ -587,9 +605,9 @@
         userId: Int,
         isInstantApp: Boolean,
         permissionName: String,
-        deviceId: Int,
+        persistentDeviceId: String,
     ): Boolean {
-        val flags = getPermissionFlagsWithPolicy(appId, userId, permissionName, deviceId)
+        val flags = getPermissionFlagsWithPolicy(appId, userId, permissionName, persistentDeviceId)
         if (!PermissionFlags.isPermissionGranted(flags)) {
             return false
         }
@@ -626,7 +644,7 @@
                         packageState,
                         userId,
                         permissionName,
-                        Context.DEVICE_ID_DEFAULT
+                        VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT
                     )
                 ) {
                     permissionName
@@ -956,12 +974,21 @@
         }
 
         val appId = packageState.appId
-        val oldFlags = getPermissionFlagsWithPolicy(appId, userId, permissionName, deviceId)
+        val persistentDeviceId = getPersistentDeviceId(deviceId)
+        if (persistentDeviceId == null) {
+            if (reportError) {
+                throw IllegalArgumentException("Cannot find persistent device Id for $deviceId")
+            }
+            return
+        }
+        val oldFlags =
+            getPermissionFlagsWithPolicy(appId, userId, permissionName, persistentDeviceId)
 
         if (permissionName !in androidPackage.requestedPermissions && oldFlags == 0) {
             if (reportError) {
                 Slog.e(
-                    LOG_TAG, "Permission $permissionName isn't requested by package $packageName"
+                    LOG_TAG,
+                    "Permission $permissionName isn't requested by package $packageName"
                 )
             }
             return
@@ -1096,8 +1123,18 @@
                 return 0
             }
 
+            val persistentDeviceId = getPersistentDeviceId(deviceId)
+            if (persistentDeviceId == null) {
+                Slog.w(LOG_TAG, "Cannot find persistent device Id for $deviceId")
+                return 0
+            }
             val flags =
-                getPermissionFlagsWithPolicy(packageState.appId, userId, permissionName, deviceId)
+                getPermissionFlagsWithPolicy(
+                    packageState.appId,
+                    userId,
+                    permissionName,
+                    persistentDeviceId
+                )
 
             return PermissionFlags.toApiFlags(flags)
         }
@@ -1127,13 +1164,24 @@
             }
                 ?: return false
 
+        val persistentDeviceId = getPersistentDeviceId(deviceId)
+        if (persistentDeviceId == null) {
+            Slog.w(LOG_TAG, "Cannot find persistent device Id for $deviceId")
+            return false
+        }
+
         service.getState {
-            if (isPermissionGranted(packageState, userId, permissionName, deviceId)) {
+            if (isPermissionGranted(packageState, userId, permissionName, persistentDeviceId)) {
                 return false
             }
 
             val flags =
-                getPermissionFlagsWithPolicy(packageState.appId, userId, permissionName, deviceId)
+                getPermissionFlagsWithPolicy(
+                    packageState.appId,
+                    userId,
+                    permissionName,
+                    persistentDeviceId
+                )
 
             return flags.hasBits(PermissionFlags.POLICY_FIXED)
         }
@@ -1183,13 +1231,19 @@
             return false
         }
 
+        val persistentDeviceId = getPersistentDeviceId(deviceId)
+        if (persistentDeviceId == null) {
+            Slog.w(LOG_TAG, "Cannot find persistent device Id for $deviceId")
+            return false
+        }
+
         val flags: Int
         service.getState {
-            if (isPermissionGranted(packageState, userId, permissionName, deviceId)) {
+            if (isPermissionGranted(packageState, userId, permissionName, persistentDeviceId)) {
                 return false
             }
 
-            flags = getPermissionFlagsWithPolicy(appId, userId, permissionName, deviceId)
+            flags = getPermissionFlagsWithPolicy(appId, userId, permissionName, persistentDeviceId)
         }
         if (flags.hasAnyBit(UNREQUESTABLE_MASK)) {
             return false
@@ -1463,7 +1517,13 @@
             return
         }
 
-        val oldFlags = getPermissionFlagsWithPolicy(appId, userId, permissionName, deviceId)
+        val persistentDeviceId = getPersistentDeviceId(deviceId)
+        if (persistentDeviceId == null) {
+            Slog.e(LOG_TAG, "Cannot find persistent device Id for $deviceId")
+            return
+        }
+        val oldFlags =
+            getPermissionFlagsWithPolicy(appId, userId, permissionName, persistentDeviceId)
         if (!isPermissionRequested && oldFlags == 0) {
             Slog.w(
                 LOG_TAG,
@@ -1549,10 +1609,12 @@
         appId: Int,
         userId: Int,
         permissionName: String,
-        deviceId: Int,
+        persistentDeviceId: String,
     ): Int {
-        return if (!Flags.deviceAwarePermissionApisEnabled() ||
-            deviceId == Context.DEVICE_ID_DEFAULT) {
+        return if (
+            !Flags.deviceAwarePermissionApisEnabled() ||
+                persistentDeviceId == VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT
+        ) {
             with(policy) { getPermissionFlags(appId, userId, permissionName) }
         } else {
             if (permissionName !in DEVICE_AWARE_PERMISSIONS) {
@@ -1563,19 +1625,8 @@
                 )
                 return with(policy) { getPermissionFlags(appId, userId, permissionName) }
             }
-            val virtualDeviceManagerInternal = virtualDeviceManagerInternal
-            if (virtualDeviceManagerInternal == null) {
-                Slog.e(LOG_TAG, "Virtual device manager service is not available.")
-                return 0
-            }
-            val persistentDeviceId = virtualDeviceManagerInternal.getPersistentIdForDevice(deviceId)
-            if (persistentDeviceId != null) {
-                with(devicePolicy) {
-                    getPermissionFlags(appId, persistentDeviceId, userId, permissionName)
-                }
-            } else {
-                Slog.e(LOG_TAG, "Invalid device ID $deviceId.")
-                0
+            with(devicePolicy) {
+                getPermissionFlags(appId, persistentDeviceId, userId, permissionName)
             }
         }
     }
@@ -1587,8 +1638,9 @@
         deviceId: Int,
         flags: Int
     ): Boolean {
-        return if (!Flags.deviceAwarePermissionApisEnabled() ||
-            deviceId == Context.DEVICE_ID_DEFAULT) {
+        return if (
+            !Flags.deviceAwarePermissionApisEnabled() || deviceId == Context.DEVICE_ID_DEFAULT
+        ) {
             with(policy) { setPermissionFlags(appId, userId, permissionName, flags) }
         } else {
             if (permissionName !in DEVICE_AWARE_PERMISSIONS) {
@@ -1600,23 +1652,30 @@
                 return with(policy) { setPermissionFlags(appId, userId, permissionName, flags) }
             }
 
-            val virtualDeviceManagerInternal = virtualDeviceManagerInternal
-            if (virtualDeviceManagerInternal == null) {
-                Slog.e(LOG_TAG, "Virtual device manager service is not available.")
-                return false
-            }
-            val persistentDeviceId = virtualDeviceManagerInternal.getPersistentIdForDevice(deviceId)
+            val persistentDeviceId = getPersistentDeviceId(deviceId)
             if (persistentDeviceId != null) {
                 with(devicePolicy) {
                     setPermissionFlags(appId, persistentDeviceId, userId, permissionName, flags)
                 }
             } else {
-                Slog.e(LOG_TAG, "Invalid device ID $deviceId.")
+                Slog.e(LOG_TAG, "Cannot find persistent device Id for $deviceId")
                 false
             }
         }
     }
 
+    private fun getPersistentDeviceId(deviceId: Int): String? {
+        if (deviceId == Context.DEVICE_ID_DEFAULT) {
+            return VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT
+        }
+
+        if (virtualDeviceManagerInternal == null) {
+            virtualDeviceManagerInternal =
+                LocalServices.getService(VirtualDeviceManagerInternal::class.java)
+        }
+        return virtualDeviceManagerInternal?.getPersistentIdForDevice(deviceId)
+    }
+
     /**
      * This method does not enforce checks on the caller, should only be called after required
      * checks.
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
index bb91939..067dd3b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
@@ -113,6 +113,7 @@
 import android.app.NotificationManager;
 import android.app.role.RoleManager;
 import android.app.usage.AppStandbyInfo;
+import android.companion.virtual.VirtualDeviceManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -2439,7 +2440,8 @@
         doReturn(granted ? PERMISSION_GRANTED : PERMISSION_DENIED)
                 .when(mPermissionManagerServiceInternal)
                 .checkPermission(
-                        packageName, perm, Context.DEVICE_ID_DEFAULT, UserHandle.getUserId(uid));
+                        packageName, perm, VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT,
+                        UserHandle.getUserId(uid));
         try {
             doReturn(granted ? PERMISSION_GRANTED : PERMISSION_DENIED)
                     .when(mIActivityManager)
diff --git a/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java
index 8656f60..8ef716f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java
@@ -405,7 +405,7 @@
                 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps());
         doReturn(PackageManager.PERMISSION_DENIED)
                 .when(mPermissionManager)
-                .checkPermission(anyString(), anyString(), anyInt(), anyInt());
+                .checkPermission(anyString(), anyString(), anyString(), anyInt());
         generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, USER_ID_1, INSTALLER_NAME_1, 0);
         mTestLooper.dispatchAll();
         assertEquals(
@@ -418,7 +418,7 @@
                 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps());
         doReturn(PERMISSION_GRANTED)
                 .when(mPermissionManager)
-                .checkPermission(anyString(), anyString(), anyInt(), anyInt());
+                .checkPermission(anyString(), anyString(), anyString(), anyInt());
         generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, USER_ID_1, INSTALLER_NAME_1, 0);
         mTestLooper.dispatchAll();
         assertEquals(
@@ -431,7 +431,7 @@
                 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps());
         doReturn(PERMISSION_GRANTED)
                 .when(mPermissionManager)
-                .checkPermission(anyString(), anyString(), anyInt(), anyInt());
+                .checkPermission(anyString(), anyString(), anyString(), anyInt());
         generateUsageEvent(UsageEvents.Event.USER_INTERACTION, USER_ID_1, INSTALLER_NAME_1, 0);
         mTestLooper.dispatchAll();
         assertEquals(
@@ -444,7 +444,7 @@
                 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps());
         doReturn(PERMISSION_GRANTED)
                 .when(mPermissionManager)
-                .checkPermission(anyString(), anyString(), anyInt(), anyInt());
+                .checkPermission(anyString(), anyString(), anyString(), anyInt());
         generateUsageEvent(
                 UsageEvents.Event.ACTIVITY_RESUMED,
                 USER_ID_1,
@@ -471,7 +471,7 @@
                 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps());
         doReturn(PERMISSION_GRANTED)
                 .when(mPermissionManager)
-                .checkPermission(anyString(), anyString(), anyInt(), anyInt());
+                .checkPermission(anyString(), anyString(), anyString(), anyInt());
         generateUsageEvent(
                 UsageEvents.Event.ACTIVITY_RESUMED,
                 USER_ID_1,
@@ -500,7 +500,7 @@
                 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps());
         doReturn(PERMISSION_GRANTED)
                 .when(mPermissionManager)
-                .checkPermission(anyString(), anyString(), anyInt(), anyInt());
+                .checkPermission(anyString(), anyString(), anyString(), anyInt());
         generateUsageEvent(
                 UsageEvents.Event.ACTIVITY_RESUMED,
                 USER_ID_1,
@@ -538,7 +538,7 @@
                 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps());
         doReturn(PERMISSION_GRANTED)
                 .when(mPermissionManager)
-                .checkPermission(anyString(), anyString(), anyInt(), anyInt());
+                .checkPermission(anyString(), anyString(), anyString(), anyInt());
         generateUsageEvent(
                 Event.ACTIVITY_STOPPED, USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1);
         mTestLooper.dispatchAll();
@@ -622,7 +622,7 @@
         // mBackgroundInstallControlService.getBackgroundInstalledPackages()
         doReturn(PERMISSION_GRANTED)
                 .when(mPermissionManager)
-                .checkPermission(anyString(), anyString(), anyInt(), anyInt());
+                .checkPermission(anyString(), anyString(), anyString(), anyInt());
         generateUsageEvent(
                 UsageEvents.Event.ACTIVITY_RESUMED,
                 USER_ID_1,
@@ -671,7 +671,7 @@
         // mBackgroundInstallControlService.getBackgroundInstalledPackages()
         doReturn(PERMISSION_GRANTED)
                 .when(mPermissionManager)
-                .checkPermission(anyString(), anyString(), anyInt(), anyInt());
+                .checkPermission(anyString(), anyString(), anyString(), anyInt());
         generateUsageEvent(
                 UsageEvents.Event.ACTIVITY_RESUMED,
                 USER_ID_1,
@@ -725,7 +725,7 @@
         // mBackgroundInstallControlService.getBackgroundInstalledPackages()
         doReturn(PERMISSION_GRANTED)
                 .when(mPermissionManager)
-                .checkPermission(anyString(), anyString(), anyInt(), anyInt());
+                .checkPermission(anyString(), anyString(), anyString(), anyInt());
         generateUsageEvent(
                 UsageEvents.Event.ACTIVITY_RESUMED,
                 USER_ID_2,
@@ -780,7 +780,7 @@
         // install getBackgroundInstalledPackages() is expected to return null
         doReturn(PERMISSION_GRANTED)
                 .when(mPermissionManager)
-                .checkPermission(anyString(), anyString(), anyInt(), anyInt());
+                .checkPermission(anyString(), anyString(), anyString(), anyInt());
         generateUsageEvent(
                 UsageEvents.Event.ACTIVITY_RESUMED,
                 USER_ID_1,
@@ -833,7 +833,7 @@
         // install getBackgroundInstalledPackages() is expected to return null
         doReturn(PERMISSION_GRANTED)
                 .when(mPermissionManager)
-                .checkPermission(anyString(), anyString(), anyInt(), anyInt());
+                .checkPermission(anyString(), anyString(), anyString(), anyInt());
         generateUsageEvent(
                 UsageEvents.Event.ACTIVITY_RESUMED,
                 USER_ID_1,