Merge "Make OP_LEGACY_STORAGE stickiness configurable" into rvc-dev
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index a68cc3d..aee32ed 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -162,7 +162,12 @@
     /** {@hide} */
     public static final String PROP_SETTINGS_FUSE = FeatureFlagUtils.PERSIST_PREFIX
             + FeatureFlagUtils.SETTINGS_FUSE_FLAG;
-
+    /**
+     * Property that determines whether {@link OP_LEGACY_STORAGE} is sticky for
+     * legacy apps.
+     * @hide
+     */
+    public static final String PROP_LEGACY_OP_STICKY = "persist.sys.legacy_storage_sticky";
 
     /** {@hide} */
     public static final String UUID_PRIVATE_INTERNAL = null;
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index bb94460..9018caa 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -43,6 +43,7 @@
 import static android.os.storage.OnObbStateChangeListener.MOUNTED;
 import static android.os.storage.OnObbStateChangeListener.UNMOUNTED;
 import static android.os.storage.StorageManager.PROP_FUSE;
+import static android.os.storage.StorageManager.PROP_LEGACY_OP_STICKY;
 import static android.os.storage.StorageManager.PROP_SETTINGS_FUSE;
 
 import static com.android.internal.util.XmlUtils.readIntAttribute;
@@ -903,6 +904,7 @@
                     refreshIsolatedStorageSettings();
                 }
             });
+        updateLegacyStorageOpSticky();
         // For now, simply clone property when it changes
         DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
                 mContext.getMainExecutor(), (properties) -> {
@@ -1779,6 +1781,13 @@
         }
     }
 
+    private void updateLegacyStorageOpSticky() {
+        final boolean propertyValue = DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+                "legacy_storage_op_sticky", true);
+        SystemProperties.set(PROP_LEGACY_OP_STICKY, propertyValue ? "true" : "false");
+    }
+
     private void start() {
         connectStoraged();
         connectVold();
diff --git a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
index 39aeafc..d6c48a0 100644
--- a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
+++ b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
@@ -26,6 +26,7 @@
 import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.storage.StorageManager.PROP_LEGACY_OP_STICKY;
 
 import static java.lang.Integer.min;
 
@@ -36,6 +37,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.os.Build;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.storage.StorageManagerInternal;
 
@@ -63,6 +65,9 @@
                 }
             };
 
+    private static final boolean isLegacyStorageAppOpStickyGlobal = SystemProperties.getBoolean(
+            PROP_LEGACY_OP_STICKY, /*defaultValue*/true);
+
     /**
      * TargetSDK is per package. To make sure two apps int the same shared UID do not fight over
      * what to set, always compute the combined targetSDK.
@@ -136,9 +141,12 @@
                     shouldPreserveLegacyExternalStorage = pkg.hasPreserveLegacyExternalStorage()
                             && smInternal.hasLegacyExternalStorage(appInfo.uid);
                     targetSDK = getMinimumTargetSDK(context, appInfo, user);
+                    // LEGACY_STORAGE op is normally sticky for apps targetig <= Q.
+                    // However, this device can be configured to make it non-sticky.
+                    boolean isLegacyAppOpSticky = isLegacyStorageAppOpStickyGlobal
+                            && targetSDK <= Build.VERSION_CODES.Q;
                     shouldApplyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0
-                            || (targetSDK > Build.VERSION_CODES.Q
-                            && !shouldPreserveLegacyExternalStorage);
+                            || (!isLegacyAppOpSticky && !shouldPreserveLegacyExternalStorage);
                 } else {
                     isWhiteListed = false;
                     shouldApplyRestriction = false;