summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt3
-rw-r--r--core/java/android/app/AppOpsManager.java18
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java17
-rw-r--r--core/java/android/content/pm/PackageInstaller.java13
-rw-r--r--core/java/android/content/pm/PackageParser.java6
-rw-r--r--core/java/android/content/pm/PermissionInfo.java11
-rw-r--r--core/java/android/os/Environment.java10
-rw-r--r--core/res/AndroidManifest.xml2
-rw-r--r--core/res/res/values/attrs_manifest.xml23
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java73
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java16
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java81
-rw-r--r--services/core/java/com/android/server/pm/Settings.java4
-rw-r--r--services/core/java/com/android/server/pm/permission/BasePermission.java7
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java19
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyService.java175
17 files changed, 216 insertions, 264 deletions
diff --git a/api/current.txt b/api/current.txt
index 0ff2eacce9b1..9ab8dbb78a67 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -287,7 +287,6 @@ package android {
field public static final int allowBackup = 16843392; // 0x1010280
field public static final int allowClearUserData = 16842757; // 0x1010005
field public static final int allowEmbedded = 16843765; // 0x10103f5
- field public static final int allowExternalStorageSandbox = 16844201; // 0x10105a9
field public static final int allowParallelSyncs = 16843570; // 0x1010332
field public static final int allowSingleTap = 16843353; // 0x1010259
field public static final int allowTaskReparenting = 16843268; // 0x1010204
@@ -1125,6 +1124,7 @@ package android {
field public static final int reqKeyboardType = 16843304; // 0x1010228
field public static final int reqNavigation = 16843306; // 0x101022a
field public static final int reqTouchScreen = 16843303; // 0x1010227
+ field public static final int requestLegacyExternalStorage = 16844201; // 0x10105a9
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
@@ -11859,6 +11859,7 @@ package android.content.pm {
field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.PermissionInfo> CREATOR;
field public static final int FLAG_COSTS_MONEY = 1; // 0x1
field public static final int FLAG_HARD_RESTRICTED = 4; // 0x4
+ field public static final int FLAG_IMMUTABLY_RESTRICTED = 16; // 0x10
field public static final int FLAG_INSTALLED = 1073741824; // 0x40000000
field public static final int FLAG_SOFT_RESTRICTED = 8; // 0x8
field public static final int PROTECTION_DANGEROUS = 1; // 0x1
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 6f9224481eba..8eb0a03671a5 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1752,21 +1752,21 @@ public class AppOpsManager {
AppOpsManager.MODE_ALLOWED, // VIBRATE
AppOpsManager.MODE_ALLOWED, // READ_CONTACTS
AppOpsManager.MODE_ALLOWED, // WRITE_CONTACTS
- AppOpsManager.MODE_DEFAULT, // READ_CALL_LOG
- AppOpsManager.MODE_DEFAULT, // WRITE_CALL_LOG
+ AppOpsManager.MODE_ALLOWED, // READ_CALL_LOG
+ AppOpsManager.MODE_ALLOWED, // WRITE_CALL_LOG
AppOpsManager.MODE_ALLOWED, // READ_CALENDAR
AppOpsManager.MODE_ALLOWED, // WRITE_CALENDAR
AppOpsManager.MODE_ALLOWED, // WIFI_SCAN
AppOpsManager.MODE_ALLOWED, // POST_NOTIFICATION
AppOpsManager.MODE_ALLOWED, // NEIGHBORING_CELLS
AppOpsManager.MODE_ALLOWED, // CALL_PHONE
- AppOpsManager.MODE_DEFAULT, // READ_SMS
+ AppOpsManager.MODE_ALLOWED, // READ_SMS
AppOpsManager.MODE_IGNORED, // WRITE_SMS
- AppOpsManager.MODE_DEFAULT, // RECEIVE_SMS
+ AppOpsManager.MODE_ALLOWED, // RECEIVE_SMS
AppOpsManager.MODE_ALLOWED, // RECEIVE_EMERGENCY_BROADCAST
- AppOpsManager.MODE_DEFAULT, // RECEIVE_MMS
- AppOpsManager.MODE_DEFAULT, // RECEIVE_WAP_PUSH
- AppOpsManager.MODE_DEFAULT, // SEND_SMS
+ AppOpsManager.MODE_ALLOWED, // RECEIVE_MMS
+ AppOpsManager.MODE_ALLOWED, // RECEIVE_WAP_PUSH
+ AppOpsManager.MODE_ALLOWED, // SEND_SMS
AppOpsManager.MODE_ALLOWED, // READ_ICC_SMS
AppOpsManager.MODE_ALLOWED, // WRITE_ICC_SMS
AppOpsManager.MODE_DEFAULT, // WRITE_SETTINGS
@@ -1800,10 +1800,10 @@ public class AppOpsManager {
AppOpsManager.MODE_ALLOWED, // READ_PHONE_STATE
AppOpsManager.MODE_ALLOWED, // ADD_VOICEMAIL
AppOpsManager.MODE_ALLOWED, // USE_SIP
- AppOpsManager.MODE_DEFAULT, // PROCESS_OUTGOING_CALLS
+ AppOpsManager.MODE_ALLOWED, // PROCESS_OUTGOING_CALLS
AppOpsManager.MODE_ALLOWED, // USE_FINGERPRINT
AppOpsManager.MODE_ALLOWED, // BODY_SENSORS
- AppOpsManager.MODE_DEFAULT, // READ_CELL_BROADCASTS
+ AppOpsManager.MODE_ALLOWED, // READ_CELL_BROADCASTS
AppOpsManager.MODE_ERRORED, // MOCK_LOCATION
AppOpsManager.MODE_ALLOWED, // READ_EXTERNAL_STORAGE
AppOpsManager.MODE_ALLOWED, // WRITE_EXTERNAL_STORAGE
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index deb181f4fd0a..9bc5f8055617 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -679,13 +679,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
public static final int PRIVATE_FLAG_IS_RESOURCE_OVERLAY = 1 << 28;
/**
- * Value for {@link #privateFlags}: If {@code true} this app allows
- * shared/external storage media to be a sandboxed view that only contains
- * files owned by the app.
+ * Value for {@link #privateFlags}: If {@code true} this app requests
+ * full external storage access. The request may not be honored due to
+ * policy or other reasons.
*
* @hide
*/
- public static final int PRIVATE_FLAG_ALLOW_EXTERNAL_STORAGE_SANDBOX = 1 << 29;
+ public static final int PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE = 1 << 29;
/**
* Value for {@link #privateFlags}: whether this app is pre-installed on the
@@ -723,7 +723,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
PRIVATE_FLAG_HAS_FRAGILE_USER_DATA,
PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE,
PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE,
- PRIVATE_FLAG_ALLOW_EXTERNAL_STORAGE_SANDBOX,
+ PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE,
PRIVATE_FLAG_ODM,
})
@Retention(RetentionPolicy.SOURCE)
@@ -1858,13 +1858,12 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
}
/**
- * If {@code true} this app allows shared/external storage media to be a
- * sandboxed view that only contains files owned by the app.
+ * If {@code true} this app requested to run in the legacy storage mode.
*
* @hide
*/
- public boolean isExternalStorageSandboxAllowed() {
- return (privateFlags & PRIVATE_FLAG_ALLOW_EXTERNAL_STORAGE_SANDBOX) != 0;
+ public boolean hasRequestedLegacyExternalStorage() {
+ return (privateFlags & PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE) != 0;
}
private boolean isAllowedToUseHiddenApis() {
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 6ce682843ed5..d2f0fb3cc768 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1505,13 +1505,14 @@ public class PackageInstaller {
* allows the app to hold that permission and whitelisting a soft restricted
* permission allows the app to hold the permission in its full, unrestricted form.
*
- * <p>The whitelisted permissions would be applied as the {@link
- * PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER installer whitelist}.
+ * <p> Permissions can also be immutably restricted which means that the whitelist
+ * state of the permission can be determined only at install time and cannot be
+ * changed on updated or at a later point via the package manager APIs.
*
- * @param permissions The restricted permissions to whitelist. Pass
- * {@link #RESTRICTED_PERMISSIONS_ALL} to whitelist all permissions and
- * <code>null</code> to clear. If you want to whitelist some permissions
- * (not all) the list must contain at least one permission.
+ * <p>The whitelisted non-immutably restricted permissions would be added to
+ * the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER installer whitelist}
+ * while the immutably restricted permissions would be added to the {@link
+ * PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM system whitelist}
*
* @see PackageManager#addWhitelistedRestrictedPermission(String, String, int)
* @see PackageManager#removeWhitelistedRestrictedPermission(String, String, int)
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index bdd80e325c4b..0ea5200d202a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3700,9 +3700,9 @@ public class PackageParser {
}
if (sa.getBoolean(
- R.styleable.AndroidManifestApplication_allowExternalStorageSandbox,
- owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q)) {
- ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ALLOW_EXTERNAL_STORAGE_SANDBOX;
+ R.styleable.AndroidManifestApplication_requestLegacyExternalStorage,
+ owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.Q)) {
+ ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE;
}
ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index f838900d43d7..14340fe788f7 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -341,6 +341,17 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
public static final int FLAG_SOFT_RESTRICTED = 1<<3;
/**
+ * Flag for {@link #flags}, corresponding to <code>immutablyRestricted</code>
+ * value of {@link android.R.attr#permissionFlags}.
+ *
+ * <p>This permission is restricted immutably which means that its
+ * restriction state may be specified only on the first install of
+ * the app and will stay in this initial whitelist state until
+ * the app is uninstalled.
+ */
+ public static final int FLAG_IMMUTABLY_RESTRICTED = 1<<4;
+
+ /**
* Flag for {@link #flags}, indicating that this permission has been
* installed into the system's globally defined permissions.
*/
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index ed5c1b1e2277..dde1e6a7f5f7 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -1148,15 +1148,9 @@ public class Environment {
final Context context = AppGlobals.getInitialApplication();
final AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
- final boolean hasLegacy = appOps.checkOpNoThrow(AppOpsManager.OP_LEGACY_STORAGE,
+ return appOps.checkOpNoThrow(AppOpsManager.OP_LEGACY_STORAGE,
context.getApplicationInfo().uid,
- context.getOpPackageName()) == AppOpsManager.MODE_ALLOWED;
-
- // STOPSHIP: only use app-op once permission model has fully landed
- final boolean requestedLegacy = !AppGlobals.getInitialApplication().getApplicationInfo()
- .isExternalStorageSandboxAllowed();
-
- return !(hasLegacy || requestedLegacy);
+ context.getOpPackageName()) != AppOpsManager.MODE_ALLOWED;
}
static File getDirectory(String variableName, String defaultPath) {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index cc3b3a4c7ccb..8714bf2505bb 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -828,6 +828,7 @@
android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_sdcardRead"
android:description="@string/permdesc_sdcardRead"
+ android:permissionFlags="softRestricted|immutablyRestricted"
android:protectionLevel="dangerous" />
<!-- Allows an application to write to external storage.
@@ -848,6 +849,7 @@
android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_sdcardWrite"
android:description="@string/permdesc_sdcardWrite"
+ android:permissionFlags="softRestricted|immutablyRestricted"
android:protectionLevel="dangerous" />
<!-- Allows an application to access any geographic locations persisted in the
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index bfa57e46984b..bbc784a10db3 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -328,6 +328,12 @@
would be granted. The weak grant depends on the permission.
-->
<flag name="softRestricted" value="0x8" />
+ <!-- This permission is restricted immutably which means that its
+ restriction state may be specified only on the first install of
+ the app and will stay in this initial whitelist state until
+ the app is uninstalled.
+ -->
+ <flag name="immutablyRestricted" value="0x10" />
</attr>
<!-- Specified the name of a group that this permission is associated
@@ -1707,17 +1713,18 @@
See {@link android.media.AudioPlaybackCaptureConfiguration} for more detail.
-->
<attr name="allowAudioPlaybackCapture" format="boolean" />
- <!-- If {@code true} this app allows shared/external storage media to be
- a sandboxed view that only contains files owned by the app.
- <p>
- Sandboxed apps can continue to discover and read media belonging to other
- apps via {@code MediaStore}.
+ <!-- If {@code true} this app would like to run under the legacy storage
+ model. Note that this may not always be respected due to policy or
+ backwards compatibility reasons.
+
+ <p>Apps not requesting legacy storage can continue to discover and
+ read media belonging to other apps via {@code MediaStore}.
<p>
The default value is:
- - {@code true} for apps with targetSdkVersion >= 29 (Q).
- - {@code false} for apps with targetSdkVersion < 29.
+ - {@code false} for apps with targetSdkVersion >= 29 (Q).
+ - {@code true} for apps with targetSdkVersion < 29.
-->
- <attr name="allowExternalStorageSandbox" format="boolean" />
+ <attr name="requestLegacyExternalStorage" format="boolean" />
</declare-styleable>
<!-- The <code>permission</code> tag declares a security permission that can be
used to control access from other packages to specific components or
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index b7d61c8f8d39..a7af144ab9ed 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2942,7 +2942,7 @@
<public name="allowClearUserDataOnFailedRestore"/>
<public name="allowAudioPlaybackCapture"/>
<public name="secureElementName" />
- <public name="allowExternalStorageSandbox"/>
+ <public name="requestLegacyExternalStorage"/>
<public name="ensuringStatusBarContrastWhenTransparent" />
<public name="ensuringNavigationBarContrastWhenTransparent" />
<public name="identifier" />
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 382fdec94f08..cdc7b269a2a2 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -293,7 +293,6 @@ class StorageManagerService extends IStorageManager.Stub
private static final String TAG_VOLUMES = "volumes";
private static final String ATTR_VERSION = "version";
private static final String ATTR_PRIMARY_STORAGE_UUID = "primaryStorageUuid";
- private static final String ATTR_ISOLATED_STORAGE = "isolatedStorage";
private static final String TAG_VOLUME = "volume";
private static final String ATTR_TYPE = "type";
private static final String ATTR_FS_UUID = "fsUuid";
@@ -349,10 +348,6 @@ class StorageManagerService extends IStorageManager.Stub
@GuardedBy("mLock")
private String mPrimaryStorageUuid;
- /** Flag indicating isolated storage state of last boot */
- @GuardedBy("mLock")
- private boolean mLastIsolatedStorage = false;
-
/** Map from disk ID to latches */
@GuardedBy("mLock")
private ArrayMap<String, CountDownLatch> mDiskScanLatches = new ArrayMap<>();
@@ -1681,63 +1676,6 @@ class StorageManagerService extends IStorageManager.Stub
mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
} catch (RemoteException e) {
}
-
- synchronized (mLock) {
- final boolean thisIsolatedStorage = StorageManager.hasIsolatedStorage();
- if (mLastIsolatedStorage != thisIsolatedStorage) {
- if (thisIsolatedStorage) {
- // This boot enables isolated storage; apply legacy behavior
- applyLegacyStorage();
- }
-
- // Always remember the new state we just booted with
- writeSettingsLocked();
- }
- }
- }
-
- /**
- * 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,
- user).getPackageManager();
- } catch (PackageManager.NameNotFoundException e) {
- throw new RuntimeException(e);
- }
-
- final List<PackageInfo> pkgs = pm.getPackagesHoldingPermissions(
- ALL_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;
-
- final long lastAccess = getLastAccessTime(appOps, uid, packageName, new int[] {
- AppOpsManager.OP_READ_EXTERNAL_STORAGE,
- AppOpsManager.OP_WRITE_EXTERNAL_STORAGE,
- });
-
- Log.d(TAG, "Found " + uid + " " + packageName
- + " with granted storage access, last accessed " + lastAccess);
- if (lastAccess > 0) {
- appOps.setUidMode(AppOpsManager.OP_LEGACY_STORAGE, uid,
- AppOpsManager.MODE_ALLOWED);
- }
- }
- }
}
private static long getLastAccessTime(AppOpsManager manager,
@@ -1783,7 +1721,6 @@ class StorageManagerService extends IStorageManager.Stub
private void readSettingsLocked() {
mRecords.clear();
mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
- mLastIsolatedStorage = false;
FileInputStream fis = null;
try {
@@ -1805,9 +1742,6 @@ class StorageManagerService extends IStorageManager.Stub
mPrimaryStorageUuid = readStringAttribute(in,
ATTR_PRIMARY_STORAGE_UUID);
}
- mLastIsolatedStorage = readBooleanAttribute(in,
- ATTR_ISOLATED_STORAGE, false);
-
} else if (TAG_VOLUME.equals(tag)) {
final VolumeRecord rec = readVolumeRecord(in);
mRecords.put(rec.fsUuid, rec);
@@ -1837,7 +1771,6 @@ class StorageManagerService extends IStorageManager.Stub
out.startTag(null, TAG_VOLUMES);
writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY);
writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid);
- writeBooleanAttribute(out, ATTR_ISOLATED_STORAGE, StorageManager.hasIsolatedStorage());
final int size = mRecords.size();
for (int i = 0; i < size; i++) {
final VolumeRecord rec = mRecords.valueAt(i);
@@ -3800,11 +3733,7 @@ class StorageManagerService extends IStorageManager.Stub
// they hold the runtime permission
final boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE,
uid, packageName) == MODE_ALLOWED;
- // STOPSHIP: only use app-op once permission model has fully landed
- final boolean requestedLegacy = !mIPackageManager
- .getApplicationInfo(packageName, 0, UserHandle.getUserId(uid))
- .isExternalStorageSandboxAllowed();
- if ((hasLegacy || requestedLegacy) && hasStorage) {
+ if (hasLegacy && hasStorage) {
return Zygote.MOUNT_EXTERNAL_LEGACY;
} else {
return Zygote.MOUNT_EXTERNAL_WRITE;
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 873cadb5a9d9..cd8167ae4653 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -3097,6 +3097,7 @@ public class AppOpsService extends IAppOpsService.Stub {
int nonpackageUid;
final static Binder sBinder = new Binder();
IBinder mToken;
+ boolean targetsUid;
Shell(IAppOpsService iface, AppOpsService internal) {
mInterface = iface;
@@ -3190,6 +3191,8 @@ public class AppOpsService extends IAppOpsService.Stub {
for (String argument; (argument = getNextArg()) != null;) {
if ("--user".equals(argument)) {
userId = UserHandle.parseUserArg(getNextArgRequired());
+ } else if ("--uid".equals(argument)) {
+ targetsUid = true;
} else {
if (packageName == null) {
packageName = argument;
@@ -3288,7 +3291,7 @@ public class AppOpsService extends IAppOpsService.Stub {
pw.println(" Starts a given operation for a particular application.");
pw.println(" stop [--user <USER_ID>] <PACKAGE | UID> <OP> ");
pw.println(" Stops a given operation for a particular application.");
- pw.println(" set [--user <USER_ID>] <PACKAGE | UID> <OP> <MODE>");
+ pw.println(" set [--user <USER_ID>] <--uid PACKAGE | PACKAGE | UID> <OP> <MODE>");
pw.println(" Set the mode for a particular application and operation.");
pw.println(" get [--user <USER_ID>] <PACKAGE | UID> [<OP>]");
pw.println(" Return the mode for a particular application and optional operation.");
@@ -3306,6 +3309,7 @@ public class AppOpsService extends IAppOpsService.Stub {
pw.println(" <MODE> one of allow, ignore, deny, or default");
pw.println(" <USER_ID> the user id under which the package is installed. If --user is not");
pw.println(" specified, the current user is assumed.");
+ pw.println(" --uid PACKAGE refer to the UID of the package");
}
static int onShellCommand(Shell shell, String cmd) {
@@ -3332,9 +3336,17 @@ public class AppOpsService extends IAppOpsService.Stub {
return -1;
}
- if (shell.packageName != null) {
+ if (!shell.targetsUid && shell.packageName != null) {
shell.mInterface.setMode(shell.op, shell.packageUid, shell.packageName,
mode);
+ } else if (shell.targetsUid && shell.packageName != null) {
+ try {
+ final int uid = shell.mInternal.mContext.getPackageManager()
+ .getPackageUid(shell.packageName, shell.userId);
+ shell.mInterface.setUidMode(shell.op, uid, mode);
+ } catch (PackageManager.NameNotFoundException e) {
+ return -1;
+ }
} else {
shell.mInterface.setUidMode(shell.op, shell.nonpackageUid, mode);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7b418b51957c..e231eed3e2b6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5733,6 +5733,8 @@ public class PackageManagerService extends IPackageManager.Stub
"getWhitelistedRestrictedPermissions for user " + userId);
}
+ final PackageParser.Package pkg;
+
synchronized (mPackages) {
final PackageSetting packageSetting = mSettings.mPackages.get(packageName);
if (packageSetting == null) {
@@ -5740,6 +5742,8 @@ public class PackageManagerService extends IPackageManager.Stub
return null;
}
+ pkg = packageSetting.pkg;
+
final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
== PackageManager.PERMISSION_GRANTED;
@@ -5767,14 +5771,14 @@ public class PackageManagerService extends IPackageManager.Stub
UserHandle.getCallingUserId())) {
return null;
}
+ }
- final long identity = Binder.clearCallingIdentity();
- try {
- return mPermissionManager.getWhitelistedRestrictedPermissions(
- packageSetting.pkg, whitelistFlags, userId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return mPermissionManager.getWhitelistedRestrictedPermissions(
+ pkg, whitelistFlags, userId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
}
@@ -5785,6 +5789,10 @@ public class PackageManagerService extends IPackageManager.Stub
// Other argument checks are done in get/setWhitelistedRestrictedPermissions
Preconditions.checkNotNull(permission);
+ if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permission)) {
+ return false;
+ }
+
List<String> permissions = getWhitelistedRestrictedPermissions(packageName,
whitelistFlags, userId);
if (permissions == null) {
@@ -5792,13 +5800,31 @@ public class PackageManagerService extends IPackageManager.Stub
}
if (permissions.indexOf(permission) < 0) {
permissions.add(permission);
- setWhitelistedRestrictedPermissions(packageName, permissions,
+ return setWhitelistedRestrictedPermissions(packageName, permissions,
whitelistFlags, userId);
- return true;
}
return false;
}
+ private boolean checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(
+ @NonNull String permission) {
+ synchronized (mPackages) {
+ final BasePermission bp = mPermissionManager.getPermissionTEMP(permission);
+ if (bp == null) {
+ Slog.w(TAG, "No such permissions: " + permission);
+ return false;
+ }
+ if (bp.isHardOrSoftRestricted() && bp.isImmutablyRestricted()
+ && mContext.checkCallingOrSelfPermission(
+ Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Cannot modify whitelisting of an immutably "
+ + "restricted permission: " + permission);
+ }
+ return true;
+ }
+ }
+
@Override
public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName,
@NonNull String permission, @PermissionWhitelistFlags int whitelistFlags,
@@ -5806,17 +5832,20 @@ public class PackageManagerService extends IPackageManager.Stub
// Other argument checks are done in get/setWhitelistedRestrictedPermissions
Preconditions.checkNotNull(permission);
+ if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permission)) {
+ return false;
+ }
+
final List<String> permissions = getWhitelistedRestrictedPermissions(packageName,
whitelistFlags, userId);
if (permissions != null && permissions.remove(permission)) {
- setWhitelistedRestrictedPermissions(packageName, permissions,
+ return setWhitelistedRestrictedPermissions(packageName, permissions,
whitelistFlags, userId);
- return true;
}
return false;
}
- private void setWhitelistedRestrictedPermissions(@NonNull String packageName,
+ private boolean setWhitelistedRestrictedPermissions(@NonNull String packageName,
@Nullable List<String> permissions, @PermissionWhitelistFlags int whitelistFlag,
@UserIdInt int userId) {
Preconditions.checkNotNull(packageName);
@@ -5833,13 +5862,17 @@ public class PackageManagerService extends IPackageManager.Stub
"setWhitelistedRestrictedPermissions for user " + userId);
}
+ final PackageParser.Package pkg;
+
synchronized (mPackages) {
final PackageSetting packageSetting = mSettings.mPackages.get(packageName);
if (packageSetting == null) {
Slog.w(TAG, "Unknown package: " + packageName);
- return;
+ return false;
}
+ pkg = packageSetting.pkg;
+
final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
== PackageManager.PERMISSION_GRANTED;
@@ -5864,7 +5897,7 @@ public class PackageManagerService extends IPackageManager.Stub
packageName, whitelistFlag, userId);
if (permissions == null || permissions.isEmpty()) {
if (whitelistedPermissions == null || whitelistedPermissions.isEmpty()) {
- return;
+ return true;
}
} else {
// Only the system can add and remove while the installer can only remove.
@@ -5890,18 +5923,20 @@ public class PackageManagerService extends IPackageManager.Stub
if (filterAppAccessLPr(packageSetting, Binder.getCallingUid(),
UserHandle.getCallingUserId())) {
- return;
+ return false;
}
+ }
- final long identity = Binder.clearCallingIdentity();
- try {
- mPermissionManager.setWhitelistedRestrictedPermissions(packageSetting.pkg,
- new int[]{userId}, permissions, Process.myUid(), whitelistFlag,
- mPermissionCallback);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mPermissionManager.setWhitelistedRestrictedPermissions(pkg,
+ new int[]{userId}, permissions, Process.myUid(), whitelistFlag,
+ mPermissionCallback);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
+
+ return true;
}
@Override
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 41a8a776e3f7..5baeaf6595e0 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4413,7 +4413,7 @@ public final class Settings {
ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION, "PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION",
ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE, "PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE",
ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE, "ALLOW_AUDIO_PLAYBACK_CAPTURE",
- ApplicationInfo.PRIVATE_FLAG_ALLOW_EXTERNAL_STORAGE_SANDBOX, "ALLOW_EXTERNAL_STORAGE_SANDBOX",
+ ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE, "PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE",
ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND, "BACKUP_IN_FOREGROUND",
ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE",
ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE, "DEFAULT_TO_DEVICE_PROTECTED_STORAGE",
@@ -4737,7 +4737,7 @@ public final class Settings {
}
pw.print(prefix); pw.print(" "); pw.print(perm);
final BasePermission bp = mPermissions.getPermission(perm);
- if (bp != null && bp.isRestricted()) {
+ if (bp != null && bp.isHardOrSoftRestricted()) {
pw.println(": restricted=true");
} else {
pw.println();
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index 490c647c22b1..6d22faa7032e 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -203,12 +203,17 @@ public final class BasePermission {
&& (perm.info.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0;
}
- public boolean isRestricted() {
+ public boolean isHardOrSoftRestricted() {
return perm != null && perm.info != null
&& (perm.info.flags & (PermissionInfo.FLAG_HARD_RESTRICTED
| PermissionInfo.FLAG_SOFT_RESTRICTED)) != 0;
}
+ public boolean isImmutablyRestricted() {
+ return perm != null && perm.info != null
+ && (perm.info.flags & PermissionInfo.FLAG_IMMUTABLY_RESTRICTED) != 0;
+ }
+
public boolean isSignature() {
return (protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) ==
PermissionInfo.PROTECTION_SIGNATURE;
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index dd63e3ca290e..9ede263284a1 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -2059,7 +2059,7 @@ public class PermissionManagerService {
return;
}
- if (RESTRICTED_PERMISSIONS_ENABLED && bp.isRestricted()
+ if (RESTRICTED_PERMISSIONS_ENABLED && bp.isHardOrSoftRestricted()
&& (flags & PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) == 0) {
Log.e(TAG, "Cannot grant restricted non-exempt permission "
+ permName + " for package " + packageName);
@@ -2241,7 +2241,7 @@ public class PermissionManagerService {
continue;
}
- if (!bp.isRestricted()) {
+ if (!bp.isHardOrSoftRestricted()) {
continue;
}
@@ -2294,13 +2294,16 @@ public class PermissionManagerService {
updatePermissions = true;
+ final boolean wasWhitelisted = (oldFlags
+ & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
+ final boolean isWhitelisted = (newFlags
+ & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
+
// If the permission is policy fixed as granted but it is no longer
// on any of the whitelists we need to clear the policy fixed flag
// as whitelisting trumps policy i.e. policy cannot grant a non
// grantable permission.
if ((oldFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
- final boolean isWhitelisted = (newFlags
- & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
final boolean isGranted = permissionsState.hasPermission(permissionName, userId);
if (!isWhitelisted && isGranted) {
mask |= PackageManager.FLAG_PERMISSION_POLICY_FIXED;
@@ -2308,6 +2311,14 @@ public class PermissionManagerService {
}
}
+ // If we are whitelisting an app that does not support runtime permissions
+ // we need to make sure it goes through the permission review UI at launch.
+ if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
+ && !wasWhitelisted && isWhitelisted) {
+ mask |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
+ newFlags |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
+ }
+
updatePermissionFlags(permissionName, pkg.packageName, mask, newFlags,
callingUid, userId, false, null /*callback*/);
}
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 1fd8b711d348..a280d83fac27 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -19,6 +19,7 @@ package com.android.server.policy;
import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -36,9 +37,7 @@ import android.os.Process;
import android.os.UserHandle;
import android.permission.PermissionControllerManager;
import android.permission.PermissionManagerInternal;
-import android.util.ArraySet;
import android.util.Slog;
-import android.util.SparseArray;
import android.util.SparseIntArray;
import com.android.server.FgThread;
@@ -46,7 +45,6 @@ import com.android.server.LocalServices;
import com.android.server.SystemService;
import java.util.ArrayList;
-import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
@@ -57,17 +55,10 @@ import java.util.concurrent.CountDownLatch;
* and app ops - and vise versa.
*/
public final class PermissionPolicyService extends SystemService {
- private static final String PLATFORM_PACKAGE = "android";
-
private static final String LOG_TAG = PermissionPolicyService.class.getSimpleName();
- // No need to lock as this is populated on boot when the OS is
- // single threaded and is never mutated until a reboot.
- private static final ArraySet<String> sAllRestrictedPermissions = new ArraySet<>();
-
public PermissionPolicyService(@NonNull Context context) {
super(context);
- cacheAllRestrictedPermissions(context);
}
@Override
@@ -101,20 +92,6 @@ public final class PermissionPolicyService extends SystemService {
startWatchingRuntimePermissionChanges(getContext(), userId);
}
- private static void cacheAllRestrictedPermissions(@NonNull Context context) {
- try {
- final PackageInfo packageInfo = context.getPackageManager()
- .getPackageInfo(PLATFORM_PACKAGE, PackageManager.GET_PERMISSIONS);
- for (PermissionInfo permissionInfo : packageInfo.permissions) {
- if (permissionInfo.isRestricted()) {
- sAllRestrictedPermissions.add(permissionInfo.name);
- }
- }
- } catch (NameNotFoundException impossible) {
- /* cannot happen */
- }
- }
-
private static void grantOrUpgradeDefaultRuntimePermissionsInNeeded(@NonNull Context context,
@UserIdInt int userId) {
final PackageManagerInternal packageManagerInternal = LocalServices.getService(
@@ -162,7 +139,7 @@ public final class PermissionPolicyService extends SystemService {
}
private static @Nullable Context getUserContext(@NonNull Context context,
- @NonNull UserHandle user) {
+ @Nullable UserHandle user) {
if (context.getUser().equals(user)) {
return context;
} else {
@@ -230,18 +207,31 @@ public final class PermissionPolicyService extends SystemService {
private final @NonNull SparseIntArray mAllUids = new SparseIntArray();
/**
- * All ops that need to be restricted
+ * All ops that need to be set to default
+ *
+ * Currently, only used by the restricted permissions logic.
*
* @see #syncRestrictedOps
*/
- private final @NonNull ArrayList<OpToRestrict> mOpsToRestrict = new ArrayList<>();
+ private final @NonNull ArrayList<OpToRestrict> mOpsToDefault = new ArrayList<>();
/**
- * All ops that need to be unrestricted
+ * All ops that need to be flipped to allow if default.
+ *
+ * Currently, only used by the restricted permissions logic.
*
* @see #syncRestrictedOps
*/
- private final @NonNull ArrayList<OpToUnrestrict> mOpsToUnrestrict = new ArrayList<>();
+ private final @NonNull ArrayList<OpToUnrestrict> mOpsToAllow = new ArrayList<>();
+
+ /**
+ * All ops that need to be flipped to ignore if default.
+ *
+ * Currently, only used by the restricted permissions logic.
+ *
+ * @see #syncRestrictedOps
+ */
+ private final @NonNull ArrayList<OpToUnrestrict> mOpsToIgnore = new ArrayList<>();
/**
* All foreground permissions
@@ -262,89 +252,20 @@ public final class PermissionPolicyService extends SystemService {
* <p>This processes ops previously added by {@link #addOpIfRestricted}
*/
private void syncRestrictedOps() {
- final SparseIntArray unprocessedUids = mAllUids.clone();
-
- // TRICKY: we set the app op for a restricted permission to allow if the app
- // requesting the permission is whitelisted and to deny if the app requesting
- // the permission is not whitelisted. However, there is another case where an
- // app in a shared user can access a component in another app in the same shared
- // user due to being in the same shared user and not by having the permission
- // that guards the component form the rest of the world. We need to handle this.
- // The way we do this is by setting app ops corresponding to non requested
- // restricted permissions to allow as this would allow the shared uid access
- // case and be okay for other apps as they would not have the permission and
- // would fail on the permission checks before reaching the app op check.
- final SparseArray<List<String>> unrequestedRestrictedPermissionsForUid =
- new SparseArray<>();
-
- final int unrestrictCount = mOpsToUnrestrict.size();
- for (int i = 0; i < unrestrictCount; i++) {
- final OpToUnrestrict op = mOpsToUnrestrict.get(i);
- setUidModeAllowed(op.code, op.uid, op.packageName);
-
- // Keep track this permission was requested by the UID.
- List<String> unrequestedRestrictedPermissions =
- unrequestedRestrictedPermissionsForUid.get(op.uid);
- if (unrequestedRestrictedPermissions == null) {
- unrequestedRestrictedPermissions = new ArrayList<>(sAllRestrictedPermissions);
- unrequestedRestrictedPermissionsForUid.put(op.uid,
- unrequestedRestrictedPermissions);
- }
- unrequestedRestrictedPermissions.remove(AppOpsManager.opToPermission(op.code));
-
- unprocessedUids.delete(op.uid);
+ final int allowCount = mOpsToAllow.size();
+ for (int i = 0; i < allowCount; i++) {
+ final OpToUnrestrict op = mOpsToAllow.get(i);
+ setUidModeAllowedIfDefault(op.code, op.uid, op.packageName);
}
- final int restrictCount = mOpsToRestrict.size();
- for (int i = 0; i < restrictCount; i++) {
- final OpToRestrict op = mOpsToRestrict.get(i);
- setUidModeDefault(op.code, op.uid);
-
- // Keep track this permission was requested by the UID.
- List<String> unrequestedRestrictedPermissions =
- unrequestedRestrictedPermissionsForUid.get(op.uid);
- if (unrequestedRestrictedPermissions == null) {
- unrequestedRestrictedPermissions = new ArrayList<>(sAllRestrictedPermissions);
- unrequestedRestrictedPermissionsForUid.put(op.uid,
- unrequestedRestrictedPermissions);
- }
- unrequestedRestrictedPermissions.remove(AppOpsManager.opToPermission(op.code));
-
- unprocessedUids.delete(op.uid);
- }
-
- // Give root access
- unprocessedUids.put(Process.ROOT_UID, Process.ROOT_UID);
-
- // Add records for UIDs that don't use any restricted permissions.
- final int uidCount = unprocessedUids.size();
- for (int i = 0; i < uidCount; i++) {
- final int uid = unprocessedUids.keyAt(i);
- unrequestedRestrictedPermissionsForUid.put(uid,
- new ArrayList<>(sAllRestrictedPermissions));
+ final int ignoreCount = mOpsToIgnore.size();
+ for (int i = 0; i < ignoreCount; i++) {
+ final OpToUnrestrict op = mOpsToIgnore.get(i);
+ setUidModeIgnoredIfDefault(op.code, op.uid, op.packageName);
}
-
- // Flip ops for all unrequested restricted permission for the UIDs.
- final int unrequestedUidCount = unrequestedRestrictedPermissionsForUid.size();
- for (int i = 0; i < unrequestedUidCount; i++) {
- final List<String> unrequestedRestrictedPermissions =
- unrequestedRestrictedPermissionsForUid.valueAt(i);
- if (unrequestedRestrictedPermissions != null) {
- final int uid = unrequestedRestrictedPermissionsForUid.keyAt(i);
- final String[] packageNames = (uid != Process.ROOT_UID)
- ? mPackageManager.getPackagesForUid(uid)
- : new String[] {"root"};
- if (packageNames == null) {
- continue;
- }
- final int permissionCount = unrequestedRestrictedPermissions.size();
- for (int j = 0; j < permissionCount; j++) {
- final String permission = unrequestedRestrictedPermissions.get(j);
- for (String packageName : packageNames) {
- setUidModeAllowed(AppOpsManager.permissionToOpCode(permission), uid,
- packageName);
- }
- }
- }
+ final int defaultCount = mOpsToDefault.size();
+ for (int i = 0; i < defaultCount; i++) {
+ final OpToRestrict op = mOpsToDefault.get(i);
+ setUidModeDefault(op.code, op.uid);
}
}
@@ -411,12 +332,27 @@ public final class PermissionPolicyService extends SystemService {
if (permissionInfo.isHardRestricted()) {
if (applyRestriction) {
- mOpsToRestrict.add(new OpToRestrict(uid, opCode));
+ mOpsToDefault.add(new OpToRestrict(uid, opCode));
} else {
- mOpsToUnrestrict.add(new OpToUnrestrict(uid, pkg.packageName, opCode));
+ mOpsToAllow.add(new OpToUnrestrict(uid, pkg.packageName, opCode));
}
} else if (permissionInfo.isSoftRestricted()) {
- //TODO: Implement soft restrictions like storage here.
+ // Storage uses a special app op to decide the mount state and
+ // supports soft restriction where the restricted state allows
+ // the permission but only for accessing the medial collections.
+ if (Manifest.permission.READ_EXTERNAL_STORAGE.equals(permission)
+ || Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(permission)) {
+ if (applyRestriction) {
+ mOpsToDefault.add(new OpToRestrict(uid,
+ AppOpsManager.OP_LEGACY_STORAGE));
+ } else if (pkg.applicationInfo.hasRequestedLegacyExternalStorage()) {
+ mOpsToAllow.add(new OpToUnrestrict(uid, pkg.packageName,
+ AppOpsManager.OP_LEGACY_STORAGE));
+ } else {
+ mOpsToIgnore.add(new OpToUnrestrict(uid, pkg.packageName,
+ AppOpsManager.OP_LEGACY_STORAGE));
+ }
+ }
}
}
@@ -474,11 +410,20 @@ public final class PermissionPolicyService extends SystemService {
}
}
- private void setUidModeAllowed(int opCode, int uid, @NonNull String packageName) {
+ private void setUidModeAllowedIfDefault(int opCode, int uid, @NonNull String packageName) {
+ setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_ALLOWED, packageName);
+ }
+
+ private void setUidModeIgnoredIfDefault(int opCode, int uid, @NonNull String packageName) {
+ setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_IGNORED, packageName);
+ }
+
+ private void setUidModeIfDefault(int opCode, int uid, int mode,
+ @NonNull String packageName) {
final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager
.opToPublicName(opCode), uid, packageName);
if (currentMode == AppOpsManager.MODE_DEFAULT) {
- mAppOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_ALLOWED);
+ mAppOpsManager.setUidMode(opCode, uid, mode);
}
}