Manifest flag for apps to request sandboxing.
We're iterating on the design to let apps request via a manifest
flag if they'd like to opt-in or opt-out of storage sandboxing. The
default is to assume that P apps don't allow sandboxing, and that
Q apps do allow sandboxing.
Bug: 129487770
Test: manual
Change-Id: I8fddb35eed412c78622be4ccae57c7b7d2aa1286
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index cceb6ed..f7e927e 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -20,6 +20,8 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
+import android.app.AppGlobals;
+import android.app.AppOpsManager;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.os.storage.StorageManager;
@@ -1060,7 +1062,7 @@
* @throws IllegalArgumentException if the path is not a valid storage
* device.
*/
- public static boolean isExternalStorageRemovable(File path) {
+ public static boolean isExternalStorageRemovable(@NonNull File path) {
final StorageVolume volume = StorageManager.getStorageVolume(path, UserHandle.myUserId());
if (volume != null) {
return volume.isRemovable();
@@ -1103,7 +1105,7 @@
* @throws IllegalArgumentException if the path is not a valid storage
* device.
*/
- public static boolean isExternalStorageEmulated(File path) {
+ public static boolean isExternalStorageEmulated(@NonNull File path) {
final StorageVolume volume = StorageManager.getStorageVolume(path, UserHandle.myUserId());
if (volume != null) {
return volume.isEmulated();
@@ -1112,6 +1114,44 @@
}
}
+ /**
+ * Returns whether the shared/external storage media at the given path is a
+ * sandboxed view that only contains files owned by the app.
+ * <p>
+ * This value may be different from the value requested by
+ * {@code allowExternalStorageSandbox} in the app's manifest, since an app
+ * may inherit its sandboxed state based on when it was first installed.
+ * <p>
+ * Sandboxed apps can continue to discover and read media belonging to other
+ * apps via {@link android.provider.MediaStore}.
+ */
+ public static boolean isExternalStorageSandboxed() {
+ final File externalDir = sCurrentUser.getExternalDirs()[0];
+ return isExternalStorageSandboxed(externalDir);
+ }
+
+ /**
+ * Returns whether the shared/external storage media at the given path is a
+ * sandboxed view that only contains files owned by the app.
+ * <p>
+ * This value may be different from the value requested by
+ * {@code allowExternalStorageSandbox} in the app's manifest, since an app
+ * may inherit its sandboxed state based on when it was first installed.
+ * <p>
+ * Sandboxed apps can continue to discover and read media belonging to other
+ * apps via {@link android.provider.MediaStore}.
+ *
+ * @throws IllegalArgumentException if the path is not a valid storage
+ * device.
+ */
+ public static boolean isExternalStorageSandboxed(@NonNull File path) {
+ final Context context = AppGlobals.getInitialApplication();
+ final AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
+ return appOps.noteOpNoThrow(AppOpsManager.OP_LEGACY_STORAGE,
+ context.getApplicationInfo().uid,
+ context.getPackageName()) != AppOpsManager.MODE_ALLOWED;
+ }
+
static File getDirectory(String variableName, String defaultPath) {
String path = System.getenv(variableName);
return path == null ? new File(defaultPath) : new File(path);