Loading api/current.txt +2 −1 Original line number Diff line number Diff line Loading @@ -36154,6 +36154,8 @@ package android.os { method public static boolean isExternalStorageEmulated(@NonNull java.io.File); method public static boolean isExternalStorageLegacy(); method public static boolean isExternalStorageLegacy(@NonNull java.io.File); method public static boolean isExternalStorageManager(); method public static boolean isExternalStorageManager(@NonNull java.io.File); method public static boolean isExternalStorageRemovable(); method public static boolean isExternalStorageRemovable(@NonNull java.io.File); field public static String DIRECTORY_ALARMS; Loading Loading @@ -82232,4 +82234,3 @@ package org.xmlpull.v1.sax2 { } } core/java/android/os/Environment.java +45 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Objects; /** * Provides access to environment variables. Loading Loading @@ -1253,6 +1254,50 @@ public class Environment { uid, context.getOpPackageName()) == AppOpsManager.MODE_ALLOWED; } /** * Returns whether the calling app has All Files Access on the primary shared/external storage * media. * <p>Declaring the permission {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} isn't * enough to gain the access. * <p>To request access, use * {@link android.provider.Settings#ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION}. */ public static boolean isExternalStorageManager() { final File externalDir = sCurrentUser.getExternalDirs()[0]; return isExternalStorageManager(externalDir); } /** * Returns whether the calling app has All Files Access at the given {@code path} * <p>Declaring the permission {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} isn't * enough to gain the access. * <p>To request access, use * {@link android.provider.Settings#ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION}. */ public static boolean isExternalStorageManager(@NonNull File path) { final Context context = Objects.requireNonNull(AppGlobals.getInitialApplication()); String packageName = Objects.requireNonNull(context.getPackageName()); int uid = context.getApplicationInfo().uid; final AppOpsManager appOps = context.getSystemService(AppOpsManager.class); final int opMode = appOps.checkOpNoThrow(AppOpsManager.OP_MANAGE_EXTERNAL_STORAGE, uid, packageName); switch (opMode) { case AppOpsManager.MODE_DEFAULT: return PackageManager.PERMISSION_GRANTED == context.checkPermission( Manifest.permission.MANAGE_EXTERNAL_STORAGE, Process.myPid(), uid); case AppOpsManager.MODE_ALLOWED: return true; case AppOpsManager.MODE_ERRORED: case AppOpsManager.MODE_IGNORED: return false; default: throw new IllegalStateException("Unknown AppOpsManager mode " + opMode); } } static File getDirectory(String variableName, String defaultPath) { String path = System.getenv(variableName); return path == null ? new File(defaultPath) : new File(path); Loading core/tests/coretests/src/android/os/EnvironmentTest.java +40 −1 Original line number Diff line number Diff line Loading @@ -23,7 +23,10 @@ import static android.os.Environment.HAS_OTHER; import static android.os.Environment.classifyExternalStorageDirectory; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import android.app.AppOpsManager; import android.content.Context; import androidx.test.InstrumentationRegistry; Loading @@ -40,10 +43,33 @@ import java.io.File; public class EnvironmentTest { private File dir; private Context getContext() { private static Context getContext() { return InstrumentationRegistry.getContext(); } /** * Sets {@code mode} for the given {@code ops} and the given {@code uid}. * * <p>This method drops shell permission identity. */ private static void setAppOpsModeForUid(int uid, int mode, String... ops) { if (ops == null) { return; } InstrumentationRegistry.getInstrumentation() .getUiAutomation() .adoptShellPermissionIdentity(); try { for (String op : ops) { getContext().getSystemService(AppOpsManager.class).setUidMode(op, uid, mode); } } finally { InstrumentationRegistry.getInstrumentation() .getUiAutomation() .dropShellPermissionIdentity(); } } @Before public void setUp() throws Exception { dir = getContext().getDir("testing", Context.MODE_PRIVATE); Loading Loading @@ -101,4 +127,17 @@ public class EnvironmentTest { Environment.buildPath(dir, "Taxes.pdf").createNewFile(); assertEquals(HAS_OTHER, classifyExternalStorageDirectory(dir)); } @Test public void testIsExternalStorageManager() throws Exception { assertFalse(Environment.isExternalStorageManager()); try { setAppOpsModeForUid(Process.myUid(), AppOpsManager.MODE_ALLOWED, AppOpsManager.OPSTR_MANAGE_EXTERNAL_STORAGE); assertTrue(Environment.isExternalStorageManager()); } finally { setAppOpsModeForUid(Process.myUid(), AppOpsManager.MODE_DEFAULT, AppOpsManager.OPSTR_MANAGE_EXTERNAL_STORAGE); } } } Loading
api/current.txt +2 −1 Original line number Diff line number Diff line Loading @@ -36154,6 +36154,8 @@ package android.os { method public static boolean isExternalStorageEmulated(@NonNull java.io.File); method public static boolean isExternalStorageLegacy(); method public static boolean isExternalStorageLegacy(@NonNull java.io.File); method public static boolean isExternalStorageManager(); method public static boolean isExternalStorageManager(@NonNull java.io.File); method public static boolean isExternalStorageRemovable(); method public static boolean isExternalStorageRemovable(@NonNull java.io.File); field public static String DIRECTORY_ALARMS; Loading Loading @@ -82232,4 +82234,3 @@ package org.xmlpull.v1.sax2 { } }
core/java/android/os/Environment.java +45 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Objects; /** * Provides access to environment variables. Loading Loading @@ -1253,6 +1254,50 @@ public class Environment { uid, context.getOpPackageName()) == AppOpsManager.MODE_ALLOWED; } /** * Returns whether the calling app has All Files Access on the primary shared/external storage * media. * <p>Declaring the permission {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} isn't * enough to gain the access. * <p>To request access, use * {@link android.provider.Settings#ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION}. */ public static boolean isExternalStorageManager() { final File externalDir = sCurrentUser.getExternalDirs()[0]; return isExternalStorageManager(externalDir); } /** * Returns whether the calling app has All Files Access at the given {@code path} * <p>Declaring the permission {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} isn't * enough to gain the access. * <p>To request access, use * {@link android.provider.Settings#ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION}. */ public static boolean isExternalStorageManager(@NonNull File path) { final Context context = Objects.requireNonNull(AppGlobals.getInitialApplication()); String packageName = Objects.requireNonNull(context.getPackageName()); int uid = context.getApplicationInfo().uid; final AppOpsManager appOps = context.getSystemService(AppOpsManager.class); final int opMode = appOps.checkOpNoThrow(AppOpsManager.OP_MANAGE_EXTERNAL_STORAGE, uid, packageName); switch (opMode) { case AppOpsManager.MODE_DEFAULT: return PackageManager.PERMISSION_GRANTED == context.checkPermission( Manifest.permission.MANAGE_EXTERNAL_STORAGE, Process.myPid(), uid); case AppOpsManager.MODE_ALLOWED: return true; case AppOpsManager.MODE_ERRORED: case AppOpsManager.MODE_IGNORED: return false; default: throw new IllegalStateException("Unknown AppOpsManager mode " + opMode); } } static File getDirectory(String variableName, String defaultPath) { String path = System.getenv(variableName); return path == null ? new File(defaultPath) : new File(path); Loading
core/tests/coretests/src/android/os/EnvironmentTest.java +40 −1 Original line number Diff line number Diff line Loading @@ -23,7 +23,10 @@ import static android.os.Environment.HAS_OTHER; import static android.os.Environment.classifyExternalStorageDirectory; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import android.app.AppOpsManager; import android.content.Context; import androidx.test.InstrumentationRegistry; Loading @@ -40,10 +43,33 @@ import java.io.File; public class EnvironmentTest { private File dir; private Context getContext() { private static Context getContext() { return InstrumentationRegistry.getContext(); } /** * Sets {@code mode} for the given {@code ops} and the given {@code uid}. * * <p>This method drops shell permission identity. */ private static void setAppOpsModeForUid(int uid, int mode, String... ops) { if (ops == null) { return; } InstrumentationRegistry.getInstrumentation() .getUiAutomation() .adoptShellPermissionIdentity(); try { for (String op : ops) { getContext().getSystemService(AppOpsManager.class).setUidMode(op, uid, mode); } } finally { InstrumentationRegistry.getInstrumentation() .getUiAutomation() .dropShellPermissionIdentity(); } } @Before public void setUp() throws Exception { dir = getContext().getDir("testing", Context.MODE_PRIVATE); Loading Loading @@ -101,4 +127,17 @@ public class EnvironmentTest { Environment.buildPath(dir, "Taxes.pdf").createNewFile(); assertEquals(HAS_OTHER, classifyExternalStorageDirectory(dir)); } @Test public void testIsExternalStorageManager() throws Exception { assertFalse(Environment.isExternalStorageManager()); try { setAppOpsModeForUid(Process.myUid(), AppOpsManager.MODE_ALLOWED, AppOpsManager.OPSTR_MANAGE_EXTERNAL_STORAGE); assertTrue(Environment.isExternalStorageManager()); } finally { setAppOpsModeForUid(Process.myUid(), AppOpsManager.MODE_DEFAULT, AppOpsManager.OPSTR_MANAGE_EXTERNAL_STORAGE); } } }