diff options
| author | 2019-09-19 16:35:44 -0700 | |
|---|---|---|
| committer | 2019-09-27 16:37:37 -0700 | |
| commit | fa291701d263e88f7a6ce38f7da9bb866340e66d (patch) | |
| tree | 71e67018dfb844f3e1ed25a9d69194d5653a98df | |
| parent | d262c51aaa34d30c5eb2a73d244cb927af5d9e45 (diff) | |
Use REVOKED_COMPAT instead of MODE_DEFAULT when syncing app ops.
To get rid of yet another permission state stored in app ops.
MODE_DEFAULT was used to record that the app op is set to a denied
mode by restricted permissions, in contrast to the MODE_IGNORED set
when user denies a permission. However since we have the
REVOKED_COMPAT flag now, we can just use MODE_IGNORED and get rid of
the permission state stored in app op and related logic for it.
Bug: 136503238
Test: manual
Change-Id: I2199188d7feeb37359ad2cb5e7621a3930488e5f
3 files changed, 137 insertions, 327 deletions
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 7953c50def7e..fc8d52005a1c 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 @@ public class PermissionManagerService extends IPermissionManager.Stub { } 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 @@ public class PermissionManagerService extends IPermissionManager.Stub { 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 @@ public class PermissionManagerService extends IPermissionManager.Stub { 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 a98de8909d85..2f667133d64f 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 @@ public final class PermissionPolicyService extends SystemService { 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 @@ public final class PermissionPolicyService extends SystemService { 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,20 +401,20 @@ public final class PermissionPolicyService extends SystemService { 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. + * All ops that need to be flipped to ignore. * * @see #syncPackages */ - private final @NonNull ArrayList<OpToChange> mOpsToIgnoreIfDefault = new ArrayList<>(); + private final @NonNull ArrayList<OpToChange> mOpsToIgnore = new ArrayList<>(); /** - * All ops that need to be flipped to ignore. + * 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> mOpsToIgnore = new ArrayList<>(); + private final @NonNull ArrayList<OpToChange> mOpsToIgnoreIfNotAllowed = new ArrayList<>(); /** * All ops that need to be flipped to foreground. @@ -481,19 +460,6 @@ public final class PermissionPolicyService extends SystemService { 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 @@ public final class PermissionPolicyService extends SystemService { 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 @@ public final class PermissionPolicyService extends SystemService { 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,58 +689,49 @@ public final class PermissionPolicyService extends SystemService { } } - 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 void setUidMode(int opCode, int uid, int mode, + private boolean setUidModeIgnoredIfNotAllowed(int opCode, int uid, @NonNull String packageName) { - final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager - .opToPublicName(opCode), uid, packageName); - - if (currentMode != mode) { - mAppOpsManager.setUidMode(opCode, uid, mode); + 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 boolean setUidModeIfMode(int opCode, int uid, int requiredModeBefore, int newMode, + private void setUidMode(int opCode, int uid, int mode, @NonNull String packageName) { final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager .opToPublicName(opCode), uid, packageName); - - if (currentMode == requiredModeBefore) { - mAppOpsManager.setUidMode(opCode, uid, newMode); - return true; + if (currentMode != mode) { + mAppOpsManager.setUidMode(opCode, uid, mode); } - - return false; - } - - private void setUidModeDefault(int opCode, int uid, String packageName) { - setUidMode(opCode, uid, MODE_DEFAULT, packageName); } private class OpToChange { diff --git a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java index 34c925826502..b0f22e4248ba 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 @@ package com.android.server.policy; 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.app.AppOpsManager; 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 @@ public abstract class SoftRestrictedPermissionPolicy { 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 @@ public abstract class SoftRestrictedPermissionPolicy { * 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 @@ public abstract class SoftRestrictedPermissionPolicy { // 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() { - return OP_LEGACY_STORAGE; + public boolean mayGrantPermission() { + return isWhiteListed || targetSDK >= Build.VERSION_CODES.Q; } - @Override - public int getDesiredOpMode() { - if (applyRestriction) { - return MODE_DEFAULT; - } else if (hasRequestedLegacyExternalStorage) { - return MODE_ALLOWED; - } else { - return MODE_IGNORED; - } + public int getExtraAppOpCode() { + return OP_LEGACY_STORAGE; } - @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; + public boolean mayAllowExtraAppOp() { + return !shouldApplyRestriction && hasRequestedLegacyExternalStorage; } - @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 @@ public abstract class SoftRestrictedPermissionPolicy { 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 @@ public abstract class SoftRestrictedPermissionPolicy { } } - /** - * 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; - } - } - }; + 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; } - default: - return DUMMY_POLICY; } + return false; } /** - * @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. + * @return If the permission can be granted */ - public abstract int resolveAppOp(); + public abstract boolean mayGrantPermission(); /** - * @return The mode the {@link #resolveAppOp() app op} should be in. + * @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 @AppOpsManager.Mode int getDesiredOpMode(); + public int getExtraAppOpCode() { + return OP_NONE; + } /** - * @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 granted. */ - public abstract boolean shouldSetAppOpIfNotDefault(); + public boolean mayAllowExtraAppOp() { + return false; + } /** - * @return If the permission can be granted + * @return Whether the {@link #getExtraAppOpCode() app op} may be denied if was granted. */ - public abstract boolean canBeGranted(); + public boolean mayDenyExtraAppOpIfGranted() { + return false; + } } |