Merge "Use REVOKED_COMPAT instead of MODE_DEFAULT when syncing app ops."
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 7953c50..fc8d520 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1302,7 +1302,7 @@
}
if (bp.isSoftRestricted() && !SoftRestrictedPermissionPolicy.forPermission(mContext,
- pkg, UserHandle.of(userId), permName).canBeGranted()) {
+ pkg.toAppInfo(), UserHandle.of(userId), permName).mayGrantPermission()) {
Log.e(TAG, "Cannot grant soft restricted permission " + permName + " for package "
+ packageName);
return;
@@ -3361,6 +3361,9 @@
final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
| PackageManager.FLAG_PERMISSION_POLICY_FIXED;
+ final int compatFlags = PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
+ | PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
+
final boolean supportsRuntimePermissions = pkg.getTargetSdkVersion()
>= Build.VERSION_CODES.M;
@@ -3384,12 +3387,11 @@
callingUid, userId, callback);
}
} else {
- // In permission review mode we clear the review flag when we
- // are asked to install the app with all permissions granted.
- if ((flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
- updatePermissionFlagsInternal(permission, pkg.getPackageName(),
- PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, 0, callingUid,
- userId, false, callback);
+ // In permission review mode we clear the review flag and the revoked compat
+ // flag when we are asked to install the app with all permissions granted.
+ if ((flags & compatFlags) != 0) {
+ updatePermissionFlagsInternal(permission, pkg.getPackageName(), compatFlags,
+ 0, callingUid, userId, false, callback);
}
}
}
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index a98de89..2f66713 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -17,13 +17,12 @@
package com.android.server.policy;
import static android.app.AppOpsManager.MODE_ALLOWED;
-import static android.app.AppOpsManager.MODE_DEFAULT;
-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_NONE;
import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import android.annotation.NonNull;
@@ -157,14 +156,12 @@
appOpsService.startWatchingMode(getSwitchOp(perm.name), null, appOpsListener);
} else if (perm.isSoftRestricted()) {
appOpsService.startWatchingMode(getSwitchOp(perm.name), null, appOpsListener);
-
SoftRestrictedPermissionPolicy policy =
- SoftRestrictedPermissionPolicy.forPermission(null,
- (AndroidPackage) null, null,
+ SoftRestrictedPermissionPolicy.forPermission(null, null, null,
perm.name);
- if (policy.resolveAppOp() != OP_NONE) {
- appOpsService.startWatchingMode(policy.resolveAppOp(), null,
- appOpsListener);
+ int extraAppOp = policy.getExtraAppOpCode();
+ if (extraAppOp != OP_NONE) {
+ appOpsService.startWatchingMode(extraAppOp, null, appOpsListener);
}
}
}
@@ -397,24 +394,6 @@
private final @NonNull SparseIntArray mAllUids = new SparseIntArray();
/**
- * All ops that need to be set to default
- *
- * Currently, only used by the restricted permissions logic.
- *
- * @see #syncPackages
- */
- private final @NonNull ArrayList<OpToChange> mOpsToDefault = new ArrayList<>();
-
- /**
- * All ops that need to be flipped to allow if default.
- *
- * Currently, only used by the restricted permissions logic.
- *
- * @see #syncPackages
- */
- private final @NonNull ArrayList<OpToChange> mOpsToAllowIfDefault = new ArrayList<>();
-
- /**
* All ops that need to be flipped to allow.
*
* @see #syncPackages
@@ -422,15 +401,6 @@
private final @NonNull ArrayList<OpToChange> mOpsToAllow = new ArrayList<>();
/**
- * All ops that need to be flipped to ignore if default.
- *
- * Currently, only used by the restricted permissions logic.
- *
- * @see #syncPackages
- */
- private final @NonNull ArrayList<OpToChange> mOpsToIgnoreIfDefault = new ArrayList<>();
-
- /**
* All ops that need to be flipped to ignore.
*
* @see #syncPackages
@@ -438,6 +408,15 @@
private final @NonNull ArrayList<OpToChange> mOpsToIgnore = new ArrayList<>();
/**
+ * All ops that need to be flipped to ignore if not allowed.
+ *
+ * Currently, only used by soft restricted permissions logic.
+ *
+ * @see #syncPackages
+ */
+ private final @NonNull ArrayList<OpToChange> mOpsToIgnoreIfNotAllowed = new ArrayList<>();
+
+ /**
* All ops that need to be flipped to foreground.
*
* Currently, only used by the foreground/background permissions logic.
@@ -481,19 +460,6 @@
alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
- final int allowIfDefaultCount = mOpsToAllowIfDefault.size();
- for (int i = 0; i < allowIfDefaultCount; i++) {
- final OpToChange op = mOpsToAllowIfDefault.get(i);
- if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
- continue;
- }
-
- boolean wasSet = setUidModeAllowedIfDefault(op.code, op.uid, op.packageName);
- if (wasSet) {
- alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
- }
- }
-
final int foregroundIfAllowedCount = mOpsToForegroundIfAllow.size();
for (int i = 0; i < foregroundIfAllowedCount; i++) {
final OpToChange op = mOpsToForegroundIfAllow.get(i);
@@ -529,29 +495,18 @@
alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
- final int ignoreIfDefaultCount = mOpsToIgnoreIfDefault.size();
- for (int i = 0; i < ignoreIfDefaultCount; i++) {
- final OpToChange op = mOpsToIgnoreIfDefault.get(i);
+ final int ignoreIfNotAllowedCount = mOpsToIgnoreIfNotAllowed.size();
+ for (int i = 0; i < ignoreIfNotAllowedCount; i++) {
+ final OpToChange op = mOpsToIgnoreIfNotAllowed.get(i);
if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
continue;
}
- boolean wasSet = setUidModeIgnoredIfDefault(op.code, op.uid, op.packageName);
+ boolean wasSet = setUidModeIgnoredIfNotAllowed(op.code, op.uid, op.packageName);
if (wasSet) {
alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
}
-
- final int defaultCount = mOpsToDefault.size();
- for (int i = 0; i < defaultCount; i++) {
- final OpToChange op = mOpsToDefault.get(i);
- if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
- continue;
- }
-
- setUidModeDefault(op.code, op.uid, op.packageName);
- alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
- }
}
/**
@@ -573,60 +528,49 @@
return;
}
- final boolean applyRestriction =
- (mPackageManager.getPermissionFlags(permission, pkg.packageName,
- mContext.getUser()) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
-
- if (permissionInfo.isHardRestricted()) {
- if (opCode != OP_NONE) {
- if (applyRestriction) {
- mOpsToDefault.add(new OpToChange(uid, pkg.packageName, opCode));
- } else {
- mOpsToAllowIfDefault.add(new OpToChange(uid, pkg.packageName, opCode));
+ if (opCode != OP_NONE) {
+ int permissionFlags = mPackageManager.getPermissionFlags(permission,
+ pkg.packageName, mContext.getUser());
+ boolean isReviewRequired = (permissionFlags & FLAG_PERMISSION_REVIEW_REQUIRED) != 0;
+ if (!isReviewRequired) {
+ boolean isRevokedCompat =
+ (permissionFlags & FLAG_PERMISSION_REVOKED_COMPAT) != 0;
+ if (permissionInfo.isHardRestricted()) {
+ boolean shouldApplyRestriction =
+ (permissionFlags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
+ if (isRevokedCompat || shouldApplyRestriction) {
+ mOpsToIgnore.add(new OpToChange(uid, pkg.packageName, opCode));
+ } else {
+ mOpsToAllow.add(new OpToChange(uid, pkg.packageName, opCode));
+ }
+ } else if (permissionInfo.isSoftRestricted()) {
+ SoftRestrictedPermissionPolicy policy =
+ SoftRestrictedPermissionPolicy.forPermission(mContext,
+ pkg.applicationInfo, mContext.getUser(), permission);
+ if (!isRevokedCompat && policy.mayGrantPermission()) {
+ mOpsToAllow.add(new OpToChange(uid, pkg.packageName, opCode));
+ } else {
+ mOpsToIgnore.add(new OpToChange(uid, pkg.packageName, opCode));
+ }
}
}
- } else if (permissionInfo.isSoftRestricted()) {
- final SoftRestrictedPermissionPolicy policy =
+ }
+
+ if (permissionInfo.isSoftRestricted()) {
+ SoftRestrictedPermissionPolicy policy =
SoftRestrictedPermissionPolicy.forPermission(mContext, pkg.applicationInfo,
mContext.getUser(), permission);
-
- if (opCode != OP_NONE) {
- if (policy.canBeGranted()) {
- mOpsToAllowIfDefault.add(new OpToChange(uid, pkg.packageName, opCode));
+ int extraOpCode = policy.getExtraAppOpCode();
+ if (extraOpCode != OP_NONE) {
+ if (policy.mayAllowExtraAppOp()) {
+ mOpsToAllow.add(new OpToChange(uid, pkg.packageName, extraOpCode));
} else {
- mOpsToDefault.add(new OpToChange(uid, pkg.packageName, opCode));
- }
- }
-
- final int op = policy.resolveAppOp();
- if (op != OP_NONE) {
- switch (policy.getDesiredOpMode()) {
- case MODE_DEFAULT:
- mOpsToDefault.add(new OpToChange(uid, pkg.packageName, op));
- break;
- case MODE_ALLOWED:
- if (policy.shouldSetAppOpIfNotDefault()) {
- mOpsToAllow.add(new OpToChange(uid, pkg.packageName, op));
- } else {
- mOpsToAllowIfDefault.add(
- new OpToChange(uid, pkg.packageName, op));
- }
- break;
- case MODE_FOREGROUND:
- Slog.wtf(LOG_TAG,
- "Setting appop to foreground is not implemented");
- break;
- case MODE_IGNORED:
- if (policy.shouldSetAppOpIfNotDefault()) {
- mOpsToIgnore.add(new OpToChange(uid, pkg.packageName, op));
- } else {
- mOpsToIgnoreIfDefault.add(
- new OpToChange(uid, pkg.packageName,
- op));
- }
- break;
- case MODE_ERRORED:
- Slog.wtf(LOG_TAG, "Setting appop to errored is not implemented");
+ if (policy.mayDenyExtraAppOpIfGranted()) {
+ mOpsToIgnore.add(new OpToChange(uid, pkg.packageName, extraOpCode));
+ } else {
+ mOpsToIgnoreIfNotAllowed.add(new OpToChange(uid, pkg.packageName,
+ extraOpCode));
+ }
}
}
}
@@ -745,60 +689,51 @@
}
}
- private boolean setUidModeAllowedIfDefault(int opCode, int uid,
- @NonNull String packageName) {
- return setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_ALLOWED, packageName);
- }
-
private void setUidModeAllowed(int opCode, int uid, @NonNull String packageName) {
setUidMode(opCode, uid, MODE_ALLOWED, packageName);
}
private boolean setUidModeForegroundIfAllow(int opCode, int uid,
@NonNull String packageName) {
- return setUidModeIfMode(opCode, uid, MODE_ALLOWED, MODE_FOREGROUND, packageName);
+ final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName(
+ opCode), uid, packageName);
+ if (currentMode == MODE_ALLOWED) {
+ mAppOpsManager.setUidMode(opCode, uid, MODE_FOREGROUND);
+ return true;
+ }
+ return false;
}
private void setUidModeForeground(int opCode, int uid, @NonNull String packageName) {
setUidMode(opCode, uid, MODE_FOREGROUND, packageName);
}
- private boolean setUidModeIgnoredIfDefault(int opCode, int uid,
- @NonNull String packageName) {
- return setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_IGNORED, packageName);
- }
-
private void setUidModeIgnored(int opCode, int uid, @NonNull String packageName) {
setUidMode(opCode, uid, MODE_IGNORED, packageName);
}
+ private boolean setUidModeIgnoredIfNotAllowed(int opCode, int uid,
+ @NonNull String packageName) {
+ final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName(
+ opCode), uid, packageName);
+ if (currentMode != MODE_ALLOWED) {
+ if (currentMode != MODE_IGNORED) {
+ mAppOpsManager.setUidMode(opCode, uid, MODE_IGNORED);
+ }
+ return true;
+ }
+ return false;
+ }
+
private void setUidMode(int opCode, int uid, int mode,
@NonNull String packageName) {
final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager
.opToPublicName(opCode), uid, packageName);
-
if (currentMode != mode) {
mAppOpsManager.setUidMode(opCode, uid, mode);
}
}
- private boolean setUidModeIfMode(int opCode, int uid, int requiredModeBefore, int newMode,
- @NonNull String packageName) {
- final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager
- .opToPublicName(opCode), uid, packageName);
-
- if (currentMode == requiredModeBefore) {
- mAppOpsManager.setUidMode(opCode, uid, newMode);
- return true;
- }
-
- return false;
- }
-
- private void setUidModeDefault(int opCode, int uid, String packageName) {
- setUidMode(opCode, uid, MODE_DEFAULT, packageName);
- }
-
private class OpToChange {
final int uid;
final @NonNull String packageName;
diff --git a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
index 34c9258..b0f22e4 100644
--- a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
+++ b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
@@ -18,9 +18,6 @@
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
-import static android.app.AppOpsManager.MODE_ALLOWED;
-import static android.app.AppOpsManager.MODE_DEFAULT;
-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.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
@@ -36,7 +33,6 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.content.pm.parsing.AndroidPackage;
import android.os.Build;
import android.os.UserHandle;
@@ -56,22 +52,7 @@
private static final SoftRestrictedPermissionPolicy DUMMY_POLICY =
new SoftRestrictedPermissionPolicy() {
@Override
- public int resolveAppOp() {
- return OP_NONE;
- }
-
- @Override
- public int getDesiredOpMode() {
- return MODE_DEFAULT;
- }
-
- @Override
- public boolean shouldSetAppOpIfNotDefault() {
- return false;
- }
-
- @Override
- public boolean canBeGranted() {
+ public boolean mayGrantPermission() {
return true;
}
};
@@ -115,10 +96,8 @@
* Get the policy for a soft restricted permission.
*
* @param context A context to use
- * @param appInfo The application the permission belongs to. Can be {@code null}, but then
- * only {@link #resolveAppOp} will work.
- * @param user The user the app belongs to. Can be {@code null}, but then only
- * {@link #resolveAppOp} will work.
+ * @param appInfo The application the permission belongs to.
+ * @param user The user the app belongs to.
* @param permission The name of the permission
*
* @return The policy for this permission
@@ -131,82 +110,46 @@
// where the restricted state allows the permission but only for accessing the medial
// collections.
case READ_EXTERNAL_STORAGE: {
- final int flags;
- final boolean applyRestriction;
final boolean isWhiteListed;
- final boolean hasRequestedLegacyExternalStorage;
+ boolean shouldApplyRestriction;
final int targetSDK;
+ final boolean hasRequestedLegacyExternalStorage;
if (appInfo != null) {
PackageManager pm = context.getPackageManager();
- flags = pm.getPermissionFlags(permission, appInfo.packageName, user);
- applyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
+ int flags = pm.getPermissionFlags(permission, appInfo.packageName, user);
isWhiteListed = (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;
+ shouldApplyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
targetSDK = getMinimumTargetSDK(context, appInfo, user);
-
- boolean hasAnyRequestedLegacyExternalStorage =
- appInfo.hasRequestedLegacyExternalStorage();
-
- // hasRequestedLegacyExternalStorage is per package. To make sure two apps in
- // the same shared UID do not fight over what to set, always compute the
- // combined hasRequestedLegacyExternalStorage
- String[] uidPkgs = pm.getPackagesForUid(appInfo.uid);
- if (uidPkgs != null) {
- for (String uidPkg : uidPkgs) {
- if (!uidPkg.equals(appInfo.packageName)) {
- ApplicationInfo uidPkgInfo;
- try {
- uidPkgInfo = pm.getApplicationInfoAsUser(uidPkg, 0, user);
- } catch (PackageManager.NameNotFoundException e) {
- continue;
- }
-
- hasAnyRequestedLegacyExternalStorage |=
- uidPkgInfo.hasRequestedLegacyExternalStorage();
- }
- }
- }
-
- hasRequestedLegacyExternalStorage = hasAnyRequestedLegacyExternalStorage;
+ hasRequestedLegacyExternalStorage = hasUidRequestedLegacyExternalStorage(
+ appInfo.uid, context);
} else {
- flags = 0;
- applyRestriction = false;
isWhiteListed = false;
- hasRequestedLegacyExternalStorage = false;
+ shouldApplyRestriction = false;
targetSDK = 0;
+ hasRequestedLegacyExternalStorage = false;
}
+ // We have a check in PermissionPolicyService.PermissionToOpSynchroniser.setUidMode
+ // to prevent apps losing files in legacy storage, because we are holding the
+ // package manager lock here. If we ever remove this policy that check should be
+ // removed as well.
return new SoftRestrictedPermissionPolicy() {
@Override
- public int resolveAppOp() {
+ public boolean mayGrantPermission() {
+ return isWhiteListed || targetSDK >= Build.VERSION_CODES.Q;
+ }
+ @Override
+ public int getExtraAppOpCode() {
return OP_LEGACY_STORAGE;
}
-
@Override
- public int getDesiredOpMode() {
- if (applyRestriction) {
- return MODE_DEFAULT;
- } else if (hasRequestedLegacyExternalStorage) {
- return MODE_ALLOWED;
- } else {
- return MODE_IGNORED;
- }
+ public boolean mayAllowExtraAppOp() {
+ return !shouldApplyRestriction && hasRequestedLegacyExternalStorage;
}
-
@Override
- public boolean shouldSetAppOpIfNotDefault() {
- // Do not switch from allowed -> ignored as this would mean to retroactively
- // turn on isolated storage. This will make the app loose all its files.
- return getDesiredOpMode() != MODE_IGNORED;
- }
-
- @Override
- public boolean canBeGranted() {
- if (isWhiteListed || targetSDK >= Build.VERSION_CODES.Q) {
- return true;
- } else {
- return false;
- }
+ public boolean mayDenyExtraAppOpIfGranted() {
+ return shouldApplyRestriction;
}
};
}
@@ -226,22 +169,7 @@
return new SoftRestrictedPermissionPolicy() {
@Override
- public int resolveAppOp() {
- return OP_NONE;
- }
-
- @Override
- public int getDesiredOpMode() {
- return MODE_DEFAULT;
- }
-
- @Override
- public boolean shouldSetAppOpIfNotDefault() {
- return false;
- }
-
- @Override
- public boolean canBeGranted() {
+ public boolean mayGrantPermission() {
return isWhiteListed || targetSDK >= Build.VERSION_CODES.Q;
}
};
@@ -251,106 +179,51 @@
}
}
- /**
- * Get the policy for a soft restricted permission.
- *
- * @param context A context to use
- * @param pkg The application the permission belongs to. Can be {@code null}, but then
- * only {@link #resolveAppOp} will work.
- * @param user The user the app belongs to. Can be {@code null}, but then only
- * {@link #resolveAppOp} will work.
- * @param permission The name of the permission
- *
- * @return The policy for this permission
- */
- public static @NonNull SoftRestrictedPermissionPolicy forPermission(@NonNull Context context,
- @Nullable AndroidPackage pkg, @Nullable UserHandle user,
- @NonNull String permission) {
- switch (permission) {
- // 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.
- case READ_EXTERNAL_STORAGE:
- case WRITE_EXTERNAL_STORAGE: {
- final int flags;
- final boolean applyRestriction;
- final boolean isWhiteListed;
- final boolean hasRequestedLegacyExternalStorage;
- final int targetSDK;
-
- if (pkg != null) {
- flags = context.getPackageManager().getPermissionFlags(permission,
- pkg.getPackageName(), user);
- applyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
- isWhiteListed = (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;
- hasRequestedLegacyExternalStorage = pkg.hasRequestedLegacyExternalStorage();
- targetSDK = pkg.getTargetSdkVersion();
- } else {
- flags = 0;
- applyRestriction = false;
- isWhiteListed = false;
- hasRequestedLegacyExternalStorage = false;
- targetSDK = 0;
- }
-
- return new SoftRestrictedPermissionPolicy() {
- @Override
- public int resolveAppOp() {
- return OP_LEGACY_STORAGE;
- }
-
- @Override
- public int getDesiredOpMode() {
- if (applyRestriction) {
- return MODE_DEFAULT;
- } else if (hasRequestedLegacyExternalStorage) {
- return MODE_ALLOWED;
- } else {
- return MODE_IGNORED;
- }
- }
-
- @Override
- public boolean shouldSetAppOpIfNotDefault() {
- // Do not switch from allowed -> ignored as this would mean to retroactively
- // turn on isolated storage. This will make the app loose all its files.
- return getDesiredOpMode() != MODE_IGNORED;
- }
-
- @Override
- public boolean canBeGranted() {
- if (isWhiteListed || targetSDK >= Build.VERSION_CODES.Q) {
- return true;
- } else {
- return false;
- }
- }
- };
- }
- default:
- return DUMMY_POLICY;
+ private static boolean hasUidRequestedLegacyExternalStorage(int uid, @NonNull Context context) {
+ PackageManager packageManager = context.getPackageManager();
+ String[] packageNames = packageManager.getPackagesForUid(uid);
+ if (packageNames == null) {
+ return false;
}
+ UserHandle user = UserHandle.getUserHandleForUid(uid);
+ for (String packageName : packageNames) {
+ ApplicationInfo applicationInfo;
+ try {
+ applicationInfo = packageManager.getApplicationInfoAsUser(packageName, 0, user);
+ } catch (PackageManager.NameNotFoundException e) {
+ continue;
+ }
+ if (applicationInfo.hasRequestedLegacyExternalStorage()) {
+ return true;
+ }
+ }
+ return false;
}
/**
+ * @return If the permission can be granted
+ */
+ public abstract boolean mayGrantPermission();
+
+ /**
* @return An app op to be changed based on the state of the permission or
* {@link AppOpsManager#OP_NONE} if not app-op should be set.
*/
- public abstract int resolveAppOp();
+ public int getExtraAppOpCode() {
+ return OP_NONE;
+ }
/**
- * @return The mode the {@link #resolveAppOp() app op} should be in.
+ * @return Whether the {@link #getExtraAppOpCode() app op} may be granted.
*/
- public abstract @AppOpsManager.Mode int getDesiredOpMode();
+ public boolean mayAllowExtraAppOp() {
+ return false;
+ }
/**
- * @return If the {@link #resolveAppOp() app op} should be set even if the app-op is currently
- * not {@link AppOpsManager#MODE_DEFAULT}.
+ * @return Whether the {@link #getExtraAppOpCode() app op} may be denied if was granted.
*/
- public abstract boolean shouldSetAppOpIfNotDefault();
-
- /**
- * @return If the permission can be granted
- */
- public abstract boolean canBeGranted();
+ public boolean mayDenyExtraAppOpIfGranted() {
+ return false;
+ }
}