diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index a68cc3dfe0e43..aee32ed769acd 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -162,7 +162,12 @@ public class StorageManager { /** {@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 bb9446078da65..9018caa8d7b64 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.ERROR_PERMISSION_DENIE 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 @@ class StorageManagerService extends IStorageManager.Stub refreshIsolatedStorageSettings(); } }); + updateLegacyStorageOpSticky(); // For now, simply clone property when it changes DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, mContext.getMainExecutor(), (properties) -> { @@ -1779,6 +1781,13 @@ class StorageManagerService extends IStorageManager.Stub } } + 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 39aeafc345ea6..d6c48a00d33d7 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_INST 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.Context; 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 @@ public abstract class SoftRestrictedPermissionPolicy { } }; + 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 @@ public abstract class SoftRestrictedPermissionPolicy { 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;