Merge "Implement dual-permission model for storage."
This commit is contained in:
@@ -339,6 +339,7 @@ package android.app {
|
||||
field public static final String OPSTR_GET_ACCOUNTS = "android:get_accounts";
|
||||
field public static final String OPSTR_GPS = "android:gps";
|
||||
field public static final String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground";
|
||||
field public static final String OPSTR_LEGACY_STORAGE = "android:legacy_storage";
|
||||
field public static final String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels";
|
||||
field public static final String OPSTR_MUTE_MICROPHONE = "android:mute_microphone";
|
||||
field public static final String OPSTR_NEIGHBORING_CELLS = "android:neighboring_cells";
|
||||
@@ -1649,6 +1650,7 @@ package android.content.pm {
|
||||
field public static final String FEATURE_BROADCAST_RADIO = "android.hardware.broadcastradio";
|
||||
field public static final String FEATURE_TELEPHONY_CARRIERLOCK = "android.hardware.telephony.carrierlock";
|
||||
field public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 32; // 0x20
|
||||
field public static final int FLAG_PERMISSION_HIDDEN = 1024; // 0x400
|
||||
field public static final int FLAG_PERMISSION_POLICY_FIXED = 4; // 0x4
|
||||
field public static final int FLAG_PERMISSION_REVIEW_REQUIRED = 64; // 0x40
|
||||
field public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 8; // 0x8
|
||||
@@ -1719,7 +1721,7 @@ package android.content.pm {
|
||||
method public void onPermissionsChanged(int);
|
||||
}
|
||||
|
||||
@IntDef(prefix={"FLAG_PERMISSION_"}, value={android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET, android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE, android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface PackageManager.PermissionFlags {
|
||||
@IntDef(prefix={"FLAG_PERMISSION_"}, value={android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET, android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE, android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED, android.content.pm.PackageManager.FLAG_PERMISSION_HIDDEN}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface PackageManager.PermissionFlags {
|
||||
}
|
||||
|
||||
public class PermissionGroupInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
|
||||
|
||||
@@ -172,6 +172,7 @@ package android.app {
|
||||
field public static final String OPSTR_GET_ACCOUNTS = "android:get_accounts";
|
||||
field public static final String OPSTR_GPS = "android:gps";
|
||||
field public static final String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground";
|
||||
field public static final String OPSTR_LEGACY_STORAGE = "android:legacy_storage";
|
||||
field public static final String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels";
|
||||
field public static final String OPSTR_MUTE_MICROPHONE = "android:mute_microphone";
|
||||
field public static final String OPSTR_NEIGHBORING_CELLS = "android:neighboring_cells";
|
||||
@@ -659,6 +660,7 @@ package android.content.pm {
|
||||
method @RequiresPermission(anyOf={"android.permission.GRANT_RUNTIME_PERMISSIONS", "android.permission.REVOKE_RUNTIME_PERMISSIONS"}) public abstract void updatePermissionFlags(String, String, int, int, @NonNull android.os.UserHandle);
|
||||
field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
|
||||
field public static final String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption";
|
||||
field public static final int FLAG_PERMISSION_HIDDEN = 1024; // 0x400
|
||||
field public static final int FLAG_PERMISSION_REVIEW_REQUIRED = 64; // 0x40
|
||||
field public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 8; // 0x8
|
||||
field public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED = 128; // 0x80
|
||||
|
||||
@@ -48,7 +48,6 @@ import android.util.LongSparseLongArray;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
import com.android.internal.annotations.Immutable;
|
||||
import com.android.internal.app.IAppOpsActiveCallback;
|
||||
import com.android.internal.app.IAppOpsCallback;
|
||||
@@ -1098,6 +1097,8 @@ public class AppOpsManager {
|
||||
/** @hide Write media of image type. */
|
||||
public static final String OPSTR_WRITE_MEDIA_IMAGES = "android:write_media_images";
|
||||
/** @hide Has a legacy (non-isolated) view of storage. */
|
||||
@TestApi
|
||||
@SystemApi
|
||||
public static final String OPSTR_LEGACY_STORAGE = "android:legacy_storage";
|
||||
/** @hide Interact with accessibility. */
|
||||
@SystemApi
|
||||
|
||||
@@ -3064,6 +3064,15 @@ public abstract class PackageManager {
|
||||
@SystemApi
|
||||
public static final int FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED = 1 << 9;
|
||||
|
||||
/**
|
||||
* Permission flag: The permission should not be shown in the UI.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@TestApi
|
||||
public static final int FLAG_PERMISSION_HIDDEN = 1 << 10;
|
||||
|
||||
/**
|
||||
* Mask for all permission flags present in Android P
|
||||
*
|
||||
@@ -3082,7 +3091,7 @@ public abstract class PackageManager {
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int MASK_PERMISSION_FLAGS_ALL = 0x3FF;
|
||||
public static final int MASK_PERMISSION_FLAGS_ALL = 0x7FF;
|
||||
|
||||
/**
|
||||
* Injected activity in app that forwards user to setting activity of that app.
|
||||
@@ -3793,6 +3802,7 @@ public abstract class PackageManager {
|
||||
FLAG_PERMISSION_GRANTED_BY_DEFAULT,
|
||||
FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED,
|
||||
FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED,
|
||||
FLAG_PERMISSION_HIDDEN,
|
||||
/*
|
||||
FLAG_PERMISSION_REVOKE_WHEN_REQUESED
|
||||
*/
|
||||
@@ -6586,6 +6596,7 @@ public abstract class PackageManager {
|
||||
case FLAG_PERMISSION_REVOKE_WHEN_REQUESTED: return "REVOKE_WHEN_REQUESTED";
|
||||
case FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED: return "USER_SENSITIVE_WHEN_GRANTED";
|
||||
case FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED: return "USER_SENSITIVE_WHEN_DENIED";
|
||||
case FLAG_PERMISSION_HIDDEN: return "HIDDEN";
|
||||
default: return Integer.toString(flag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -819,8 +819,7 @@
|
||||
android:permissionGroup="android.permission-group.UNDEFINED"
|
||||
android:label="@string/permlab_sdcardRead"
|
||||
android:description="@string/permdesc_sdcardRead"
|
||||
android:protectionLevel="dangerous"
|
||||
android:permissionFlags="removed" />
|
||||
android:protectionLevel="dangerous" />
|
||||
|
||||
<!-- Allows an application to write to external storage.
|
||||
<p class="note"><strong>Note:</strong> If <em>both</em> your <a
|
||||
@@ -841,8 +840,7 @@
|
||||
android:permissionGroup="android.permission-group.UNDEFINED"
|
||||
android:label="@string/permlab_sdcardWrite"
|
||||
android:description="@string/permdesc_sdcardWrite"
|
||||
android:protectionLevel="dangerous"
|
||||
android:permissionFlags="removed" />
|
||||
android:protectionLevel="dangerous" />
|
||||
|
||||
<!-- Runtime permission controlling access to the user's shared aural media
|
||||
collection. -->
|
||||
|
||||
@@ -202,17 +202,15 @@
|
||||
<new-permission name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||
</split-permission>
|
||||
|
||||
<!-- Apps holding either the legacy READ or WRITE permissions will inherit
|
||||
the ability to <em>read</em> new typed permissions in the Q release; they
|
||||
won't gain the ability to <em>write</em> that content. -->
|
||||
<!-- STOPSHIP(b/112545973): change targetSdk to Q when SDK version finalised -->
|
||||
<!-- STOPSHIP: change targetSdk to Q when SDK version finalised -->
|
||||
<!-- Old apps might not understand the modern permission model, hence their view needs to be expanded -->
|
||||
<split-permission name="android.permission.READ_EXTERNAL_STORAGE"
|
||||
targetSdk="10000">
|
||||
<new-permission name="android.permission.READ_MEDIA_AUDIO" />
|
||||
<new-permission name="android.permission.READ_MEDIA_VIDEO" />
|
||||
<new-permission name="android.permission.READ_MEDIA_IMAGES" />
|
||||
</split-permission>
|
||||
<!-- STOPSHIP(b/112545973): change targetSdk to Q when SDK version finalised -->
|
||||
<!-- STOPSHIP: change targetSdk to Q when SDK version finalised -->
|
||||
<split-permission name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
targetSdk="10000">
|
||||
<new-permission name="android.permission.READ_MEDIA_AUDIO" />
|
||||
@@ -220,6 +218,20 @@
|
||||
<new-permission name="android.permission.READ_MEDIA_IMAGES" />
|
||||
</split-permission>
|
||||
|
||||
<!-- An app using the typed media permissions might be grandfathered and then uses the old storage model -->
|
||||
<split-permission name="android.permission.READ_MEDIA_AUDIO">
|
||||
<new-permission name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<new-permission name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
</split-permission>
|
||||
<split-permission name="android.permission.READ_MEDIA_VIDEO">
|
||||
<new-permission name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<new-permission name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
</split-permission>
|
||||
<split-permission name="android.permission.READ_MEDIA_IMAGES">
|
||||
<new-permission name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<new-permission name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
</split-permission>
|
||||
|
||||
<!-- This is a list of all the libraries available for application
|
||||
code to link against. -->
|
||||
|
||||
|
||||
@@ -21,6 +21,9 @@ import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
|
||||
import static android.app.AppOpsManager.MODE_ALLOWED;
|
||||
import static android.app.AppOpsManager.OP_LEGACY_STORAGE;
|
||||
import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES;
|
||||
import static android.content.pm.PackageManager.FLAG_PERMISSION_HIDDEN;
|
||||
import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
|
||||
import static android.content.pm.PackageManager.GET_PERMISSIONS;
|
||||
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
|
||||
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
|
||||
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
|
||||
@@ -74,6 +77,7 @@ import android.content.res.ObbInfo;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.DropBoxManager;
|
||||
import android.os.Environment;
|
||||
import android.os.Environment.UserEnvironment;
|
||||
@@ -301,6 +305,19 @@ class StorageManagerService extends IStorageManager.Stub
|
||||
private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
|
||||
private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
|
||||
|
||||
private static final String[] LEGACY_STORAGE_PERMISSIONS = {
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
};
|
||||
|
||||
private static final String[] ALL_STORAGE_PERMISSIONS = {
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
Manifest.permission.READ_MEDIA_AUDIO,
|
||||
Manifest.permission.READ_MEDIA_VIDEO,
|
||||
Manifest.permission.READ_MEDIA_IMAGES
|
||||
};
|
||||
|
||||
private final AtomicFile mSettingsFile;
|
||||
|
||||
/**
|
||||
@@ -1693,23 +1710,27 @@ class StorageManagerService extends IStorageManager.Stub
|
||||
* If we're enabling isolated storage, we need to remember which existing
|
||||
* apps have already been using shared storage, and grant them legacy access
|
||||
* to keep them running smoothly.
|
||||
*
|
||||
* @see com.android.server.pm.permission.PermissionManagerService
|
||||
* #applyLegacyStoragePermissionModel
|
||||
*/
|
||||
private void applyLegacyStorage() {
|
||||
final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
|
||||
final UserManagerInternal um = LocalServices.getService(UserManagerInternal.class);
|
||||
for (int userId : um.getUserIds()) {
|
||||
final UserHandle user = UserHandle.of(userId);
|
||||
final PackageManager pm;
|
||||
try {
|
||||
pm = mContext.createPackageContextAsUser(mContext.getPackageName(),
|
||||
0, UserHandle.of(userId)).getPackageManager();
|
||||
pm = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
|
||||
user).getPackageManager();
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
final List<PackageInfo> pkgs = pm.getPackagesHoldingPermissions(new String[] {
|
||||
android.Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
}, MATCH_UNINSTALLED_PACKAGES | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
|
||||
final List<PackageInfo> pkgs = pm.getPackagesHoldingPermissions(
|
||||
LEGACY_STORAGE_PERMISSIONS,
|
||||
MATCH_UNINSTALLED_PACKAGES | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE
|
||||
| GET_PERMISSIONS);
|
||||
for (PackageInfo pkg : pkgs) {
|
||||
final int uid = pkg.applicationInfo.uid;
|
||||
final String packageName = pkg.applicationInfo.packageName;
|
||||
@@ -1722,8 +1743,28 @@ class StorageManagerService extends IStorageManager.Stub
|
||||
Log.d(TAG, "Found " + uid + " " + packageName
|
||||
+ " with granted storage access, last accessed " + lastAccess);
|
||||
if (lastAccess > 0) {
|
||||
appOps.setMode(AppOpsManager.OP_LEGACY_STORAGE,
|
||||
uid, packageName, AppOpsManager.MODE_ALLOWED);
|
||||
appOps.setUidMode(AppOpsManager.OP_LEGACY_STORAGE, uid,
|
||||
AppOpsManager.MODE_ALLOWED);
|
||||
|
||||
// Grandfather pre-Q app by granting all permissions and fixing them. The user
|
||||
// needs to uninstall the app to revoke the permissions.
|
||||
// TODO: Deal with shard Uids
|
||||
if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q) {
|
||||
for (String perm : ALL_STORAGE_PERMISSIONS) {
|
||||
if (ArrayUtils.contains(pkg.requestedPermissions, perm)) {
|
||||
pm.grantRuntimePermission(packageName, perm, user);
|
||||
|
||||
int flags = FLAG_PERMISSION_SYSTEM_FIXED;
|
||||
if (!ArrayUtils.contains(LEGACY_STORAGE_PERMISSIONS, perm)) {
|
||||
flags |= FLAG_PERMISSION_HIDDEN;
|
||||
}
|
||||
|
||||
pm.updatePermissionFlags(perm, packageName,
|
||||
FLAG_PERMISSION_SYSTEM_FIXED | FLAG_PERMISSION_HIDDEN,
|
||||
flags, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,14 +17,20 @@
|
||||
package com.android.server.pm.permission;
|
||||
|
||||
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
|
||||
import static android.Manifest.permission.READ_MEDIA_AUDIO;
|
||||
import static android.Manifest.permission.READ_MEDIA_IMAGES;
|
||||
import static android.Manifest.permission.READ_MEDIA_VIDEO;
|
||||
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
|
||||
import static android.app.AppOpsManager.MODE_ALLOWED;
|
||||
import static android.app.AppOpsManager.MODE_ERRORED;
|
||||
import static android.app.AppOpsManager.MODE_FOREGROUND;
|
||||
import static android.app.AppOpsManager.MODE_IGNORED;
|
||||
import static android.app.AppOpsManager.OP_LEGACY_STORAGE;
|
||||
import static android.app.AppOpsManager.OP_NONE;
|
||||
import static android.app.AppOpsManager.permissionToOp;
|
||||
import static android.app.AppOpsManager.permissionToOpCode;
|
||||
import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
|
||||
import static android.content.pm.PackageManager.FLAG_PERMISSION_HIDDEN;
|
||||
import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
|
||||
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
|
||||
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
|
||||
@@ -1149,6 +1155,8 @@ public class PermissionManagerService {
|
||||
updatedUserIds);
|
||||
updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origPermissions,
|
||||
permissionsState, pkg, updatedUserIds);
|
||||
updatedUserIds = applyLegacyStoragePermissionModel(origPermissions, permissionsState,
|
||||
pkg, updatedUserIds);
|
||||
|
||||
setAppOpsLocked(permissionsState, pkg);
|
||||
}
|
||||
@@ -1467,6 +1475,179 @@ public class PermissionManagerService {
|
||||
return updatedUserIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-Q apps use READ/WRITE_EXTERNAL_STORAGE, post-Q apps use READ_MEDIA_AUDIO/VIDEO/IMAGES.
|
||||
*
|
||||
* <p>There is the special case of the grandfathered post-Q app that has all legacy and modern
|
||||
* permissions system-fixed granted. The only way to remove these permissions is to uninstall
|
||||
* the app.
|
||||
*
|
||||
* @param origPs The permission state of the package before the update
|
||||
* @param ps The permissions state of the package
|
||||
* @param pkg The package
|
||||
* @param updatedUserIds The userIds we have already been updated before
|
||||
*
|
||||
* @return The userIds that have been updated
|
||||
*
|
||||
* @see com.android.server.StorageManagerService#applyLegacyStorage()
|
||||
*/
|
||||
private @NonNull int[] applyLegacyStoragePermissionModel(@NonNull PermissionsState origPs,
|
||||
@NonNull PermissionsState ps, @NonNull PackageParser.Package pkg,
|
||||
@NonNull int[] updatedUserIds) {
|
||||
AppOpsManagerInternal appOpsManager = LocalServices.getService(AppOpsManagerInternal.class);
|
||||
int[] users = UserManagerService.getInstance().getUserIds();
|
||||
|
||||
boolean isQApp = pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q;
|
||||
boolean isPreMApp = pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M;
|
||||
int appId = getAppId(pkg.applicationInfo.uid);
|
||||
|
||||
int numRequestedPerms = pkg.requestedPermissions.size();
|
||||
for (int i = 0; i < numRequestedPerms; i++) {
|
||||
String perm = pkg.requestedPermissions.get(i);
|
||||
|
||||
boolean isLegacyStoragePermission = false;
|
||||
boolean isModernStoragePermission = false;
|
||||
switch (perm) {
|
||||
case READ_EXTERNAL_STORAGE:
|
||||
case WRITE_EXTERNAL_STORAGE:
|
||||
isLegacyStoragePermission = true;
|
||||
break;
|
||||
case READ_MEDIA_AUDIO:
|
||||
case READ_MEDIA_VIDEO:
|
||||
case READ_MEDIA_IMAGES:
|
||||
isModernStoragePermission = true;
|
||||
break;
|
||||
default:
|
||||
// 'perm' is not a storage permission, skip it
|
||||
continue;
|
||||
}
|
||||
|
||||
BasePermission bp = mSettings.getPermissionLocked(perm);
|
||||
|
||||
for (int userId : users) {
|
||||
boolean useLegacyStoragePermissionModel;
|
||||
if (isQApp) {
|
||||
useLegacyStoragePermissionModel = appOpsManager.checkOperationUnchecked(
|
||||
OP_LEGACY_STORAGE, getUid(userId, appId), pkg.packageName)
|
||||
== MODE_ALLOWED;
|
||||
} else {
|
||||
useLegacyStoragePermissionModel = true;
|
||||
}
|
||||
|
||||
int origCombinedLegacyFlags =
|
||||
origPs.getPermissionFlags(READ_EXTERNAL_STORAGE, userId)
|
||||
| origPs.getPermissionFlags(WRITE_EXTERNAL_STORAGE, userId);
|
||||
|
||||
int origCombinedModernFlags = origPs.getPermissionFlags(READ_MEDIA_AUDIO, userId)
|
||||
| origPs.getPermissionFlags(READ_MEDIA_VIDEO, userId)
|
||||
| origPs.getPermissionFlags(READ_MEDIA_IMAGES, userId);
|
||||
|
||||
boolean oldPermAreLegacyStorageModel =
|
||||
(origCombinedLegacyFlags & FLAG_PERMISSION_HIDDEN) == 0;
|
||||
boolean oldPermAreModernStorageModel =
|
||||
(origCombinedModernFlags & FLAG_PERMISSION_HIDDEN) == 0;
|
||||
|
||||
if (oldPermAreLegacyStorageModel && oldPermAreModernStorageModel) {
|
||||
// This only happens after an platform upgrade from before Q
|
||||
oldPermAreModernStorageModel = false;
|
||||
}
|
||||
|
||||
boolean shouldBeRestricted;
|
||||
boolean shouldBeFixed;
|
||||
boolean shouldBeGranted = false;
|
||||
boolean shouldBeRevoked = false;
|
||||
int userFlags = -1;
|
||||
if (useLegacyStoragePermissionModel) {
|
||||
shouldBeRestricted = isModernStoragePermission;
|
||||
shouldBeFixed = isQApp || isModernStoragePermission;
|
||||
|
||||
if (shouldBeFixed) {
|
||||
userFlags = 0;
|
||||
shouldBeGranted = true;
|
||||
shouldBeRevoked = false;
|
||||
} else if (oldPermAreModernStorageModel) {
|
||||
// Inherit grant state on permission model change
|
||||
userFlags = origCombinedModernFlags;
|
||||
|
||||
shouldBeGranted = origPs.hasRuntimePermission(READ_MEDIA_AUDIO, userId)
|
||||
|| origPs.hasRuntimePermission(READ_MEDIA_VIDEO, userId)
|
||||
|| origPs.hasRuntimePermission(READ_MEDIA_IMAGES, userId);
|
||||
|
||||
shouldBeRevoked = !shouldBeGranted;
|
||||
}
|
||||
} else {
|
||||
shouldBeRestricted = isLegacyStoragePermission;
|
||||
shouldBeFixed = isLegacyStoragePermission;
|
||||
|
||||
if (shouldBeFixed) {
|
||||
userFlags = 0;
|
||||
shouldBeGranted = true;
|
||||
shouldBeRevoked = false;
|
||||
} else if (oldPermAreLegacyStorageModel) {
|
||||
// Inherit grant state on permission model change
|
||||
userFlags = origCombinedLegacyFlags;
|
||||
|
||||
shouldBeGranted = origPs.hasRuntimePermission(READ_EXTERNAL_STORAGE, userId)
|
||||
|| origPs.hasRuntimePermission(WRITE_EXTERNAL_STORAGE, userId);
|
||||
|
||||
if ((origCombinedLegacyFlags & FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0
|
||||
&& !isPreMApp) {
|
||||
shouldBeGranted = false;
|
||||
}
|
||||
|
||||
shouldBeRevoked = !shouldBeGranted;
|
||||
}
|
||||
}
|
||||
|
||||
// Granted permissions can never be user fixed
|
||||
if (shouldBeGranted & userFlags != -1) {
|
||||
userFlags &= ~FLAG_PERMISSION_USER_FIXED;
|
||||
}
|
||||
|
||||
boolean changed = false;
|
||||
synchronized (mLock) {
|
||||
if (shouldBeGranted) {
|
||||
if (isPreMApp) {
|
||||
setAppOpMode(perm, pkg, userId, MODE_ALLOWED);
|
||||
} else if (!ps.hasRuntimePermission(perm, userId)) {
|
||||
ps.grantRuntimePermission(bp, userId);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldBeRevoked) {
|
||||
if (isPreMApp) {
|
||||
setAppOpMode(perm, pkg, userId, MODE_IGNORED);
|
||||
} else if (ps.hasRuntimePermission(perm, userId)) {
|
||||
ps.revokeRuntimePermission(bp, userId);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldBeFixed) {
|
||||
changed |= ps.updatePermissionFlags(mSettings.getPermissionLocked(perm),
|
||||
userId, FLAG_PERMISSION_SYSTEM_FIXED, FLAG_PERMISSION_SYSTEM_FIXED);
|
||||
}
|
||||
|
||||
if (userFlags != -1) {
|
||||
changed |= ps.updatePermissionFlags(mSettings.getPermissionLocked(perm),
|
||||
userId, USER_PERMISSION_FLAGS, userFlags);
|
||||
}
|
||||
|
||||
changed |= ps.updatePermissionFlags(mSettings.getPermissionLocked(perm), userId,
|
||||
FLAG_PERMISSION_HIDDEN,
|
||||
shouldBeRestricted ? FLAG_PERMISSION_HIDDEN : 0);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return updatedUserIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix app-op modes for runtime permissions.
|
||||
*
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
},
|
||||
{
|
||||
"include-filter": "android.permission.cts.PermissionFlagsTest"
|
||||
},
|
||||
{
|
||||
"include-filter": "android.permission.cts.DualStoragePermissionModelTest"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user