DO NOT MERGE: Enable ENABLE_DYNAMIC_PERMISSIONS depending on MediaProvider.

The flag is now enabled only when MediaProvider version is
high enough to have the changes that handle it.

Bug: 115619667
Test: atest UriGrantsManagerServiceTest
Change-Id: I9582bb86ecf150a2f99a911226a40bb3e1273d4d
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index 8eefd8f..e8a0379 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -51,11 +51,15 @@
 import android.app.GrantedUriPermission;
 import android.app.IUriGrantsManager;
 import android.content.ClipData;
+import android.content.ComponentName;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ModuleInfo;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PathPermission;
@@ -115,13 +119,19 @@
     private static final String TAG = "UriGrantsManagerService";
     // Maximum number of persisted Uri grants a package is allowed
     private static final int MAX_PERSISTED_URI_GRANTS = 512;
-    private static final boolean ENABLE_DYNAMIC_PERMISSIONS = false;
+    private static final boolean ENABLE_DYNAMIC_PERMISSIONS = true;
+    private static final String MEDIA_PROVIDER_MODULE_NAME = "com.android.mediaprovider";
+    private static final long MIN_DYNAMIC_PERMISSIONS_MP_VERSION = 301400000L;
 
     private final Object mLock = new Object();
+    private final Context mContext;
     private final H mH;
     ActivityManagerInternal mAmInternal;
     PackageManagerInternal mPmInternal;
 
+    private boolean isDynamicPermissionEnabledInMP = false;
+    private boolean isMPVersionChecked = false;
+
     /** File storing persisted {@link #mGrantedUriPermissions}. */
     @GuardedBy("mLock")
     private final AtomicFile mGrantFile;
@@ -148,18 +158,19 @@
     private final SparseArray<ArrayMap<GrantUri, UriPermission>>
             mGrantedUriPermissions = new SparseArray<>();
 
-    private UriGrantsManagerService() {
-        this(SystemServiceManager.ensureSystemDir());
+    private UriGrantsManagerService(Context context) {
+        this(context, SystemServiceManager.ensureSystemDir());
     }
 
-    private UriGrantsManagerService(File systemDir) {
+    private UriGrantsManagerService(Context context, File systemDir) {
+        mContext = context;
         mH = new H(IoThread.get().getLooper());
         mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"), "uri-grants");
     }
 
     @VisibleForTesting
-    static UriGrantsManagerService createForTest(File systemDir) {
-        final UriGrantsManagerService service = new UriGrantsManagerService(systemDir);
+    static UriGrantsManagerService createForTest(Context context, File systemDir) {
+        final UriGrantsManagerService service = new UriGrantsManagerService(context, systemDir);
         service.mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
         service.mPmInternal = LocalServices.getService(PackageManagerInternal.class);
         return service;
@@ -179,7 +190,7 @@
 
         public Lifecycle(Context context) {
             super(context);
-            mService = new UriGrantsManagerService();
+            mService = new UriGrantsManagerService(context);
         }
 
         @Override
@@ -991,7 +1002,9 @@
         // If this provider says that grants are always required, we need to
         // consult it directly to determine if the UID has permission
         final boolean forceMet;
-        if (ENABLE_DYNAMIC_PERMISSIONS && pi.forceUriPermissions) {
+        if (ENABLE_DYNAMIC_PERMISSIONS
+                && pi.forceUriPermissions
+                && isDynamicPermissionEnabledInMP()) {
             final int providerUserId = UserHandle.getUserId(pi.applicationInfo.uid);
             final int clientUserId = UserHandle.getUserId(uid);
             if (providerUserId == clientUserId) {
@@ -1009,6 +1022,35 @@
         return readMet && writeMet && forceMet;
     }
 
+    /**
+     * Returns true if the available MediaProvider version contains the changes that enable dynamic
+     * permission.
+     */
+    private boolean isDynamicPermissionEnabledInMP() {
+        if (isMPVersionChecked) {
+            return isDynamicPermissionEnabledInMP;
+        }
+
+        try {
+            ModuleInfo moduleInfo = mContext.getPackageManager().getModuleInfo(
+                    MEDIA_PROVIDER_MODULE_NAME, PackageManager.MODULE_APEX_NAME);
+            PackageInfo packageInfo =
+                    mContext.getPackageManager().getPackageInfo(
+                            moduleInfo.getPackageName(), PackageManager.MATCH_APEX);
+            isDynamicPermissionEnabledInMP =
+                    packageInfo.getLongVersionCode() >= MIN_DYNAMIC_PERMISSIONS_MP_VERSION;
+        } catch (NameNotFoundException e) {
+            Slog.i(TAG, "Module name not found:  " + MEDIA_PROVIDER_MODULE_NAME);
+            // If module is not found, then MP changes are expected to be there (because both this
+            // change and the module change will be mandated together for non-module builds).
+            isDynamicPermissionEnabledInMP = true;
+        } finally {
+            isMPVersionChecked = true;
+        }
+
+        return isDynamicPermissionEnabledInMP;
+    }
+
     @GuardedBy("mLock")
     private void removeUriPermissionIfNeededLocked(UriPermission perm) {
         if (perm.modeFlags != 0) {
diff --git a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java
index 614949c..1494642 100644
--- a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java
@@ -79,7 +79,9 @@
     @Before
     public void setUp() throws Exception {
         mContext = new UriGrantsMockContext(InstrumentationRegistry.getContext());
-        mService = UriGrantsManagerService.createForTest(mContext.getFilesDir()).getLocalService();
+        mService = UriGrantsManagerService
+            .createForTest(mContext, mContext.getFilesDir())
+            .getLocalService();
     }
 
     /**