Merge "Use AppOp value from local identity cache." into mainline-prod
diff --git a/src/com/android/providers/media/LocalCallingIdentity.java b/src/com/android/providers/media/LocalCallingIdentity.java
index ba22182..56e11bc 100644
--- a/src/com/android/providers/media/LocalCallingIdentity.java
+++ b/src/com/android/providers/media/LocalCallingIdentity.java
@@ -21,6 +21,7 @@
 import static android.app.AppOpsManager.permissionToOp;
 import static android.content.pm.PackageManager.PERMISSION_DENIED;
 
+import static com.android.providers.media.util.PermissionUtils.checkAppOpRequestInstallPackagesForSharedUid;
 import static com.android.providers.media.util.PermissionUtils.checkIsLegacyStorageGranted;
 import static com.android.providers.media.util.PermissionUtils.checkPermissionDelegator;
 import static com.android.providers.media.util.PermissionUtils.checkPermissionInstallPackages;
@@ -216,9 +217,17 @@
     public static final int PERMISSION_WRITE_IMAGES = 1 << 21;
 
     public static final int PERMISSION_IS_SYSTEM_GALLERY = 1 << 22;
+    /**
+     * Explicitly checks **only** for INSTALL_PACKAGES runtime permission.
+     */
     public static final int PERMISSION_INSTALL_PACKAGES = 1 << 23;
     public static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 1 << 24;
 
+    /**
+     * Checks if REQUEST_INSTALL_PACKAGES app-op is allowed for any package sharing this UID.
+     */
+    public static final int APPOP_REQUEST_INSTALL_PACKAGES_FOR_SHARED_UID = 1 << 25;
+
     private int hasPermission;
     private int hasPermissionResolved;
 
@@ -287,6 +296,9 @@
             case PERMISSION_INSTALL_PACKAGES:
                 return checkPermissionInstallPackages(
                         context, pid, uid, getPackageName(), attributionTag);
+            case APPOP_REQUEST_INSTALL_PACKAGES_FOR_SHARED_UID:
+                return checkAppOpRequestInstallPackagesForSharedUid(
+                        context, uid, getSharedPackageNames(), attributionTag);
             default:
                 return false;
         }
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index bb93287..2b23dd6 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -39,6 +39,7 @@
 
 import static com.android.providers.media.DatabaseHelper.EXTERNAL_DATABASE_NAME;
 import static com.android.providers.media.DatabaseHelper.INTERNAL_DATABASE_NAME;
+import static com.android.providers.media.LocalCallingIdentity.APPOP_REQUEST_INSTALL_PACKAGES_FOR_SHARED_UID;
 import static com.android.providers.media.LocalCallingIdentity.PERMISSION_INSTALL_PACKAGES;
 import static com.android.providers.media.LocalCallingIdentity.PERMISSION_IS_DELEGATOR;
 import static com.android.providers.media.LocalCallingIdentity.PERMISSION_IS_LEGACY_GRANTED;
@@ -7559,14 +7560,7 @@
         // one of the packages has the appop granted.
         // To maintain consistency of access in primary volume and secondary volumes use the same
         // logic as we do for Zygote.MOUNT_EXTERNAL_INSTALLER view.
-        // TODO (b/173600911): Improve performance by caching this info.
-        for (String uidPackageName : mCallingIdentity.get().getSharedPackageNames()) {
-            if (mAppOpsManager.unsafeCheckOpRawNoThrow(AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES,
-                    uid, uidPackageName) == AppOpsManager.MODE_ALLOWED) {
-                return true;
-            }
-        }
-        return false;
+        return mCallingIdentity.get().hasPermission(APPOP_REQUEST_INSTALL_PACKAGES_FOR_SHARED_UID);
     }
 
     private boolean isCallingIdentityDownloadProvider(int uid) {
diff --git a/src/com/android/providers/media/util/PermissionUtils.java b/src/com/android/providers/media/util/PermissionUtils.java
index 9593b18..349e4a4 100644
--- a/src/com/android/providers/media/util/PermissionUtils.java
+++ b/src/com/android/providers/media/util/PermissionUtils.java
@@ -23,6 +23,7 @@
 import static android.Manifest.permission.UPDATE_DEVICE_STATS;
 import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
 import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES;
 import static android.app.AppOpsManager.OPSTR_LEGACY_STORAGE;
 import static android.app.AppOpsManager.OPSTR_READ_MEDIA_AUDIO;
 import static android.app.AppOpsManager.OPSTR_READ_MEDIA_IMAGES;
@@ -206,6 +207,20 @@
                 generateAppOpMessage(packageName, sOpDescription.get()));
     }
 
+    /**
+     * Returns {@code true} if any package for the given uid has request_install_packages app op.
+     */
+    public static boolean checkAppOpRequestInstallPackagesForSharedUid(@NonNull Context context,
+            int uid, @NonNull String[] sharedPackageNames, @Nullable String attributionTag) {
+        for (String packageName : sharedPackageNames) {
+            if (checkAppOp(context, OPSTR_REQUEST_INSTALL_PACKAGES, uid, packageName,
+                    attributionTag, generateAppOpMessage(packageName, sOpDescription.get()))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @VisibleForTesting
     static boolean checkNoIsolatedStorageGranted(@NonNull Context context, int uid,
             @NonNull String packageName, @Nullable String attributionTag) {