Merge "Use compat flags to reflect the current status of legacy storage." into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-03-16 17:47:33 +00:00
committed by Android (Google) Code Review

View File

@@ -23,6 +23,7 @@ import android.annotation.TestApi;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.admin.DevicePolicyManager;
import android.compat.Compatibility;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
@@ -88,6 +89,16 @@ public class Environment {
private static final File DIR_APEX_ROOT = getDirectory(ENV_APEX_ROOT,
"/apex");
/**
* See definition in com.android.providers.media.LocalCallingIdentity
*/
private static final long DEFAULT_SCOPED_STORAGE = 149924527L;
/**
* See definition in com.android.providers.media.LocalCallingIdentity
*/
private static final long FORCE_ENABLE_SCOPED_STORAGE = 132649864L;
@UnsupportedAppUsage
private static UserEnvironment sCurrentUser;
private static boolean sUserRequired;
@@ -1191,12 +1202,13 @@ public class Environment {
}
/**
* Returns whether the primary shared/external storage media is a legacy
* view that includes files not owned by the app.
* Returns whether the shared/external storage media is a
* legacy view that includes files not owned by the app.
* <p>
* This value may be different from the value requested by
* {@code requestLegacyExternalStorage} in the app's manifest, since an app
* may inherit its legacy state based on when it was first installed.
* may inherit its legacy state based on when it was first installed, target sdk and other
* factors.
* <p>
* Non-legacy apps can continue to discover and read media belonging to
* other apps via {@link android.provider.MediaStore}.
@@ -1207,18 +1219,19 @@ public class Environment {
}
/**
* Returns whether the shared/external storage media at the given path is a
* Returns whether the shared/external storage media is a
* legacy view that includes files not owned by the app.
* <p>
* This value may be different from the value requested by
* {@code requestLegacyExternalStorage} in the app's manifest, since an app
* may inherit its legacy state based on when it was first installed.
* may inherit its legacy state based on when it was first installed, target sdk and other
* factors.
* <p>
* Non-legacy 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.
* device.
*/
public static boolean isExternalStorageLegacy(@NonNull File path) {
final Context context = AppGlobals.getInitialApplication();
@@ -1232,24 +1245,23 @@ public class Environment {
return false;
}
if (packageManager.checkPermission(Manifest.permission.WRITE_MEDIA_STORAGE,
context.getPackageName()) == PackageManager.PERMISSION_GRANTED) {
// TODO(b/150672994): Compat flags do not override instant app and isolated process's
// behavior.
boolean defaultScopedStorage = Compatibility.isChangeEnabled(DEFAULT_SCOPED_STORAGE);
boolean forceEnableScopedStorage = Compatibility.isChangeEnabled(
FORCE_ENABLE_SCOPED_STORAGE);
// if Scoped Storage is strictly enforced, the app does *not* have legacy storage access
// Note: does not require packagename/uid as this is directly called from an app process
if (isScopedStorageEnforced(defaultScopedStorage, forceEnableScopedStorage)) {
return false;
}
// if Scoped Storage is strictly disabled, the app has legacy storage access
// Note: does not require packagename/uid as this is directly called from an app process
if (isScopedStorageDisabled(defaultScopedStorage, forceEnableScopedStorage)) {
return true;
}
if (packageManager.checkPermission(Manifest.permission.INSTALL_PACKAGES,
context.getPackageName()) == PackageManager.PERMISSION_GRANTED) {
return true;
}
final AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
final String[] packagesForUid = packageManager.getPackagesForUid(uid);
for (String packageName : packagesForUid) {
if (appOps.checkOpNoThrow(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES,
uid, packageName) == AppOpsManager.MODE_ALLOWED) {
return true;
}
}
return appOps.checkOpNoThrow(AppOpsManager.OP_LEGACY_STORAGE,
uid, context.getOpPackageName()) == AppOpsManager.MODE_ALLOWED;
}
@@ -1298,6 +1310,16 @@ public class Environment {
}
}
private static boolean isScopedStorageEnforced(boolean defaultScopedStorage,
boolean forceEnableScopedStorage) {
return defaultScopedStorage && forceEnableScopedStorage;
}
private static boolean isScopedStorageDisabled(boolean defaultScopedStorage,
boolean forceEnableScopedStorage) {
return !defaultScopedStorage && !forceEnableScopedStorage;
}
static File getDirectory(String variableName, String defaultPath) {
String path = System.getenv(variableName);
return path == null ? new File(defaultPath) : new File(path);