Merge "Add API for apps to query whether they have All Files Access" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
f46b9c9656
@@ -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;
|
||||
@@ -82232,4 +82234,3 @@ package org.xmlpull.v1.sax2 {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user