Merge "Add API for apps to query whether they have All Files Access" into rvc-dev

This commit is contained in:
Zimuzo Ezeozue
2020-03-10 17:03:16 +00:00
committed by Android (Google) Code Review
3 changed files with 87 additions and 2 deletions

View File

@@ -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 {
}
}

View File

@@ -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);

View File

@@ -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);
}
}
}