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 c75a462d5bc15..dd63e3ca290e0 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -18,12 +18,6 @@ package com.android.server.pm.permission; 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_ERRORED; -import static android.app.AppOpsManager.MODE_FOREGROUND; -import static android.app.AppOpsManager.OP_NONE; -import static android.app.AppOpsManager.permissionToOp; -import static android.app.AppOpsManager.permissionToOpCode; import static android.content.pm.PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT; import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION; import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT; @@ -40,8 +34,6 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_UPGRAD import static android.content.pm.PackageManager.MASK_PERMISSION_FLAGS_ALL; import static android.content.pm.PackageManager.RESTRICTED_PERMISSIONS_ENABLED; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; -import static android.os.UserHandle.getAppId; -import static android.os.UserHandle.getUid; import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL; import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING; @@ -56,8 +48,6 @@ import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; -import android.app.AppOpsManager; -import android.app.AppOpsManagerInternal; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManager.PermissionWhitelistFlags; @@ -1309,9 +1299,6 @@ public class PermissionManagerService { updatedUserIds); updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origPermissions, permissionsState, pkg, updatedUserIds); - - // TODO: Move to PermissionPolicyService - setAppOpsLocked(permissionsState, pkg); } // Persist the runtime permissions state for users with changes. If permissions @@ -1326,23 +1313,6 @@ public class PermissionManagerService { } } - /** - * Set app op for a app-op related to a permission. - * - * @param permission The permission the app-op belongs to - * @param pkg The package the permission belongs to - * @param userId The user to be changed - * @param mode The new mode to set - */ - private void setAppOpMode(@NonNull String permission, @NonNull PackageParser.Package pkg, - @UserIdInt int userId, int mode) { - AppOpsManagerInternal appOpsInternal = LocalServices.getService( - AppOpsManagerInternal.class); - - appOpsInternal.setUidMode(permissionToOpCode(permission), - getUid(userId, getAppId(pkg.applicationInfo.uid)), mode); - } - /** * Revoke permissions that are not implicit anymore and that have * {@link PackageManager#FLAG_PERMISSION_REVOKE_WHEN_REQUESTED} set. @@ -1357,8 +1327,6 @@ public class PermissionManagerService { private @NonNull int[] revokePermissionsNoLongerImplicitLocked( @NonNull PermissionsState ps, @NonNull PackageParser.Package pkg, @NonNull int[] updatedUserIds) { - AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class); - String pkgName = pkg.packageName; boolean supportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M; @@ -1390,23 +1358,6 @@ public class PermissionManagerService { } flagsToRemove |= USER_PERMISSION_FLAGS; - - List fgPerms = mBackgroundPermissions.get(permission); - if (fgPerms != null) { - int numFgPerms = fgPerms.size(); - for (int fgPermNum = 0; fgPermNum < numFgPerms; fgPermNum++) { - String fgPerm = fgPerms.get(fgPermNum); - - int mode = appOpsManager.unsafeCheckOpRaw( - permissionToOp(fgPerm), - getUid(userId, getAppId(pkg.applicationInfo.uid)), - pkgName); - - if (mode == MODE_ALLOWED) { - setAppOpMode(fgPerm, pkg, userId, MODE_FOREGROUND); - } - } - } } ps.updatePermissionFlags(bp, userId, flagsToRemove, 0); @@ -1438,91 +1389,39 @@ public class PermissionManagerService { @NonNull ArraySet sourcePerms, @NonNull String newPerm, @NonNull PermissionsState ps, @NonNull PackageParser.Package pkg, @UserIdInt int userId) { - AppOpsManagerInternal appOpsManager = LocalServices.getService(AppOpsManagerInternal.class); String pkgName = pkg.packageName; + boolean isGranted = false; + int flags = 0; - if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { - if (permissionToOp(newPerm) != null) { - int mostLenientSourceMode = MODE_ERRORED; - int flags = 0; - - // Find most lenient source permission state. - int numSourcePerms = sourcePerms.size(); - for (int i = 0; i < numSourcePerms; i++) { - String sourcePerm = sourcePerms.valueAt(i); - - if (ps.hasRuntimePermission(sourcePerm, userId)) { - int sourceOp = permissionToOpCode(sourcePerm); - - if (sourceOp != OP_NONE) { - int mode = appOpsManager.checkOperationUnchecked(sourceOp, - getUid(userId, getAppId(pkg.applicationInfo.uid)), pkgName); - - if (mode == MODE_FOREGROUND || mode == MODE_ERRORED) { - Log.wtf(TAG, "split permission" + sourcePerm + " has app-op state " - + AppOpsManager.MODE_NAMES[mode]); - - continue; - } - - // Leniency order: allowed < ignored < default - if (mode < mostLenientSourceMode) { - mostLenientSourceMode = mode; - flags = ps.getPermissionFlags(sourcePerm, userId); - } else if (mode == mostLenientSourceMode) { - flags |= ps.getPermissionFlags(sourcePerm, userId); - } - } - } + int numSourcePerm = sourcePerms.size(); + for (int i = 0; i < numSourcePerm; i++) { + String sourcePerm = sourcePerms.valueAt(i); + if ((ps.hasRuntimePermission(sourcePerm, userId)) + || ps.hasInstallPermission(sourcePerm)) { + if (!isGranted) { + flags = 0; } - if (mostLenientSourceMode != MODE_ERRORED) { - if (DEBUG_PERMISSIONS) { - Slog.i(TAG, newPerm + " inherits app-ops state " + mostLenientSourceMode - + " from " + sourcePerms + " for " + pkgName); - } - - setAppOpMode(newPerm, pkg, userId, mostLenientSourceMode); - - // Add permission flags - ps.updatePermissionFlags(mSettings.getPermission(newPerm), userId, flags, - flags); - } - } - } else { - boolean isGranted = false; - int flags = 0; - - int numSourcePerm = sourcePerms.size(); - for (int i = 0; i < numSourcePerm; i++) { - String sourcePerm = sourcePerms.valueAt(i); - if ((ps.hasRuntimePermission(sourcePerm, userId)) - || ps.hasInstallPermission(sourcePerm)) { - if (!isGranted) { - flags = 0; - } - - isGranted = true; + isGranted = true; + flags |= ps.getPermissionFlags(sourcePerm, userId); + } else { + if (!isGranted) { flags |= ps.getPermissionFlags(sourcePerm, userId); - } else { - if (!isGranted) { - flags |= ps.getPermissionFlags(sourcePerm, userId); - } } } - - if (isGranted) { - if (DEBUG_PERMISSIONS) { - Slog.i(TAG, newPerm + " inherits runtime perm grant from " + sourcePerms - + " for " + pkgName); - } - - ps.grantRuntimePermission(mSettings.getPermissionLocked(newPerm), userId); - } - - // Add permission flags - ps.updatePermissionFlags(mSettings.getPermission(newPerm), userId, flags, flags); } + + if (isGranted) { + if (DEBUG_PERMISSIONS) { + Slog.i(TAG, newPerm + " inherits runtime perm grant from " + sourcePerms + + " for " + pkgName); + } + + ps.grantRuntimePermission(mSettings.getPermissionLocked(newPerm), userId); + } + + // Add permission flags + ps.updatePermissionFlags(mSettings.getPermission(newPerm), userId, flags, flags); } /** @@ -1632,48 +1531,6 @@ public class PermissionManagerService { return updatedUserIds; } - /** - * Fix app-op modes for runtime permissions. - * - * @param permsState The state of the permissions of the package - * @param pkg The package information - */ - private void setAppOpsLocked(@NonNull PermissionsState permsState, - @NonNull PackageParser.Package pkg) { - for (int userId : UserManagerService.getInstance().getUserIds()) { - int numPerms = pkg.requestedPermissions.size(); - for (int i = 0; i < numPerms; i++) { - String permission = pkg.requestedPermissions.get(i); - - // For pre-M apps the runtime permission do not store the state - if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { - continue; - } - - PermissionState state = permsState.getRuntimePermissionState(permission, userId); - if (state == null) { - continue; - } - - // Adjust app-op mods for foreground/background permissions. If an package used to - // have both fg and bg permission granted and it lost the bg permission during an - // upgrade the app-op mode should get downgraded to foreground. - if (state.isGranted()) { - BasePermission bp = mSettings.getPermission(permission); - - if (bp != null && bp.perm != null && bp.perm.info != null - && bp.perm.info.backgroundPermission != null) { - PermissionState bgState = permsState.getRuntimePermissionState( - bp.perm.info.backgroundPermission, userId); - - setAppOpMode(permission, pkg, userId, bgState != null && bgState.isGranted() - ? MODE_ALLOWED : MODE_FOREGROUND); - } - } - } - } - } - private boolean isNewPlatformPermissionForPackage(String perm, PackageParser.Package pkg) { boolean allowed = false; final int NP = PackageParser.NEW_PERMISSIONS.length; diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java index 67f30dc2e9fc4..1fd8b711d3482 100644 --- a/services/core/java/com/android/server/policy/PermissionPolicyService.java +++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java @@ -17,8 +17,10 @@ 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.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.AppOpsManager; import android.content.Context; @@ -29,6 +31,7 @@ import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManagerInternal.PackageListObserver; import android.content.pm.PackageParser; import android.content.pm.PermissionInfo; +import android.os.Build; import android.os.Process; import android.os.UserHandle; import android.permission.PermissionControllerManager; @@ -158,37 +161,59 @@ public final class PermissionPolicyService extends SystemService { }); } + private static @Nullable Context getUserContext(@NonNull Context context, + @NonNull UserHandle user) { + if (context.getUser().equals(user)) { + return context; + } else { + try { + return context.createPackageContextAsUser(context.getPackageName(), 0, user); + } catch (NameNotFoundException e) { + Slog.e(LOG_TAG, "Cannot create context for user " + user, e); + return null; + } + } + } + + /** + * Synchronize a single package. + */ private static void synchronizePackagePermissionsAndAppOpsForUser(@NonNull Context context, @NonNull String packageName, @UserIdInt int userId) { final PackageManagerInternal packageManagerInternal = LocalServices.getService( PackageManagerInternal.class); - final PackageParser.Package pkg = packageManagerInternal.getPackage(packageName); + final PackageInfo pkg = packageManagerInternal.getPackageInfo(packageName, 0, + Process.SYSTEM_UID, userId); if (pkg == null) { return; } - final PermissionToOpSynchroniser synchroniser = new PermissionToOpSynchroniser(context); - synchroniser.addPackage(context, pkg, userId); + final PermissionToOpSynchroniser synchroniser = new PermissionToOpSynchroniser( + getUserContext(context, UserHandle.of(userId))); + synchroniser.addPackage(pkg.packageName); final String[] sharedPkgNames = packageManagerInternal.getPackagesForSharedUserId( - pkg.mSharedUserId, userId); + pkg.sharedUserId, userId); if (sharedPkgNames != null) { for (String sharedPkgName : sharedPkgNames) { final PackageParser.Package sharedPkg = packageManagerInternal .getPackage(sharedPkgName); if (sharedPkg != null) { - synchroniser.addPackage(context, sharedPkg, userId); + synchroniser.addPackage(sharedPkg.packageName); } } } synchroniser.syncPackages(); } + /** + * Synchronize all packages + */ private static void synchronizePermissionsAndAppOpsForUser(@NonNull Context context, @UserIdInt int userId) { final PackageManagerInternal packageManagerInternal = LocalServices.getService( PackageManagerInternal.class); - final PermissionToOpSynchroniser synchronizer = new PermissionToOpSynchroniser(context); - packageManagerInternal.forEachPackage((pkg) -> - synchronizer.addPackage(context, pkg, userId)); + final PermissionToOpSynchroniser synchronizer = new PermissionToOpSynchroniser( + getUserContext(context, UserHandle.of(userId))); + packageManagerInternal.forEachPackage((pkg) -> synchronizer.addPackage(pkg.packageName)); synchronizer.syncPackages(); } @@ -198,17 +223,47 @@ public final class PermissionPolicyService extends SystemService { */ private static class PermissionToOpSynchroniser { private final @NonNull Context mContext; + private final @NonNull PackageManager mPackageManager; + private final @NonNull AppOpsManager mAppOpsManager; - private final @NonNull SparseIntArray mUids = new SparseIntArray(); - private final @NonNull SparseArray mPackageNames = new SparseArray<>(); - private final @NonNull SparseIntArray mAllowedUidOps = new SparseIntArray(); - private final @NonNull SparseIntArray mDefaultUidOps = new SparseIntArray(); + /** All uid that need to be synchronized */ + private final @NonNull SparseIntArray mAllUids = new SparseIntArray(); + + /** + * All ops that need to be restricted + * + * @see #syncRestrictedOps + */ + private final @NonNull ArrayList mOpsToRestrict = new ArrayList<>(); + + /** + * All ops that need to be unrestricted + * + * @see #syncRestrictedOps + */ + private final @NonNull ArrayList mOpsToUnrestrict = new ArrayList<>(); + + /** + * All foreground permissions + * + * @see #syncOpsOfFgPermissions() + */ + private final @NonNull ArrayList mFgPermOps = new ArrayList<>(); PermissionToOpSynchroniser(@NonNull Context context) { mContext = context; + mPackageManager = context.getPackageManager(); + mAppOpsManager = context.getSystemService(AppOpsManager.class); } - void syncPackages() { + /** + * Set app ops that belong to restricted permissions. + * + *

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 @@ -222,52 +277,48 @@ public final class PermissionPolicyService extends SystemService { final SparseArray> unrequestedRestrictedPermissionsForUid = new SparseArray<>(); - final AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class); - final int allowedCount = mAllowedUidOps.size(); - for (int i = 0; i < allowedCount; i++) { - final int opCode = mAllowedUidOps.keyAt(i); - final int uid = mAllowedUidOps.valueAt(i); - final String packageName = mPackageNames.valueAt(i); - setUidModeAllowed(appOpsManager, opCode, uid, packageName); + 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 unrequestedRestrictedPermissions = - unrequestedRestrictedPermissionsForUid.get(uid); + unrequestedRestrictedPermissionsForUid.get(op.uid); if (unrequestedRestrictedPermissions == null) { unrequestedRestrictedPermissions = new ArrayList<>(sAllRestrictedPermissions); - unrequestedRestrictedPermissionsForUid.put(uid, + unrequestedRestrictedPermissionsForUid.put(op.uid, unrequestedRestrictedPermissions); } - unrequestedRestrictedPermissions.remove(AppOpsManager.opToPermission(opCode)); + unrequestedRestrictedPermissions.remove(AppOpsManager.opToPermission(op.code)); - mUids.delete(uid); + unprocessedUids.delete(op.uid); } - final int defaultCount = mDefaultUidOps.size(); - for (int i = 0; i < defaultCount; i++) { - final int opCode = mDefaultUidOps.keyAt(i); - final int uid = mDefaultUidOps.valueAt(i); - setUidModeDefault(appOpsManager, opCode, uid); + 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 unrequestedRestrictedPermissions = - unrequestedRestrictedPermissionsForUid.get(uid); + unrequestedRestrictedPermissionsForUid.get(op.uid); if (unrequestedRestrictedPermissions == null) { unrequestedRestrictedPermissions = new ArrayList<>(sAllRestrictedPermissions); - unrequestedRestrictedPermissionsForUid.put(uid, + unrequestedRestrictedPermissionsForUid.put(op.uid, unrequestedRestrictedPermissions); } - unrequestedRestrictedPermissions.remove(AppOpsManager.opToPermission(opCode)); + unrequestedRestrictedPermissions.remove(AppOpsManager.opToPermission(op.code)); - mUids.delete(uid); + unprocessedUids.delete(op.uid); } // Give root access - mUids.put(Process.ROOT_UID, Process.ROOT_UID); + unprocessedUids.put(Process.ROOT_UID, Process.ROOT_UID); // Add records for UIDs that don't use any restricted permissions. - final int uidCount = mUids.size(); + final int uidCount = unprocessedUids.size(); for (int i = 0; i < uidCount; i++) { - final int uid = mUids.keyAt(i); + final int uid = unprocessedUids.keyAt(i); unrequestedRestrictedPermissionsForUid.put(uid, new ArrayList<>(sAllRestrictedPermissions)); } @@ -280,7 +331,7 @@ public final class PermissionPolicyService extends SystemService { if (unrequestedRestrictedPermissions != null) { final int uid = unrequestedRestrictedPermissionsForUid.keyAt(i); final String[] packageNames = (uid != Process.ROOT_UID) - ? mContext.getPackageManager().getPackagesForUid(uid) + ? mPackageManager.getPackagesForUid(uid) : new String[] {"root"}; if (packageNames == null) { continue; @@ -289,8 +340,7 @@ public final class PermissionPolicyService extends SystemService { for (int j = 0; j < permissionCount; j++) { final String permission = unrequestedRestrictedPermissions.get(j); for (String packageName : packageNames) { - setUidModeAllowed(appOpsManager, - AppOpsManager.permissionToOpCode(permission), uid, + setUidModeAllowed(AppOpsManager.permissionToOpCode(permission), uid, packageName); } } @@ -298,19 +348,115 @@ public final class PermissionPolicyService extends SystemService { } } - private void addPackage(@NonNull Context context, - @NonNull PackageParser.Package pkg, @UserIdInt int userId) { - final PackageManager packageManager = context.getPackageManager(); + /** + * Set app ops that belong to restricted permissions. + * + *

This processed ops previously added by {@link #addOpIfRestricted} + */ + private void syncOpsOfFgPermissions() { + int numFgPermOps = mFgPermOps.size(); + for (int i = 0; i < numFgPermOps; i++) { + FgPermission perm = mFgPermOps.get(i); - final int uid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.applicationInfo.uid)); - final UserHandle userHandle = UserHandle.of(userId); + if (mPackageManager.checkPermission(perm.fgPermissionName, perm.packageName) + == PackageManager.PERMISSION_GRANTED) { + if (mPackageManager.checkPermission(perm.bgPermissionName, perm.packageName) + == PackageManager.PERMISSION_GRANTED) { + mAppOpsManager.setUidMode( + AppOpsManager.permissionToOpCode(perm.fgPermissionName), perm.uid, + AppOpsManager.MODE_ALLOWED); + } else { + mAppOpsManager.setUidMode( + AppOpsManager.permissionToOpCode(perm.fgPermissionName), perm.uid, + AppOpsManager.MODE_FOREGROUND); + } + } else { + mAppOpsManager.setUidMode( + AppOpsManager.permissionToOpCode(perm.fgPermissionName), perm.uid, + AppOpsManager.MODE_IGNORED); + } + } + } - mUids.put(uid, uid); + /** + * Synchronize all previously {@link #addPackage added} packages. + */ + void syncPackages() { + syncRestrictedOps(); + syncOpsOfFgPermissions(); + } - final int permissionCount = pkg.requestedPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - final String permission = pkg.requestedPermissions.get(i); + /** + * Add op that belong to a restricted permission for later processing in + * {@link #syncRestrictedOps}. + * + *

Note: Called with the package lock held. Do not call into app-op manager. + * + * @param permissionInfo The permission that is currently looked at + * @param pkg The package looked at + */ + private void addOpIfRestricted(@NonNull PermissionInfo permissionInfo, + @NonNull PackageInfo pkg) { + final String permission = permissionInfo.name; + final int opCode = AppOpsManager.permissionToOpCode(permission); + final int uid = pkg.applicationInfo.uid; + if (!permissionInfo.isRestricted()) { + return; + } + + final boolean applyRestriction = PackageManager.RESTRICTED_PERMISSIONS_ENABLED + && (mPackageManager.getPermissionFlags(permission, pkg.packageName, + mContext.getUser()) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0; + + if (permissionInfo.isHardRestricted()) { + if (applyRestriction) { + mOpsToRestrict.add(new OpToRestrict(uid, opCode)); + } else { + mOpsToUnrestrict.add(new OpToUnrestrict(uid, pkg.packageName, opCode)); + } + } else if (permissionInfo.isSoftRestricted()) { + //TODO: Implement soft restrictions like storage here. + } + } + + private void addOpIfFgPermissions(@NonNull PermissionInfo permissionInfo, + @NonNull PackageInfo pkg) { + if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { + // Pre-M apps do not store their fg/bg state in the permissions + return; + } + + if (permissionInfo.backgroundPermission == null) { + return; + } + + mFgPermOps.add(new FgPermission(pkg.applicationInfo.uid, pkg.packageName, + permissionInfo.name, permissionInfo.backgroundPermission)); + } + + /** + * Add a package for {@link #syncPackages() processing} later. + * + *

Note: Called with the package lock held. Do not call into app-op manager. + * + * @param pkgName The package to add for later processing. + */ + void addPackage(@NonNull String pkgName) { + final PackageInfo pkg; + try { + pkg = mPackageManager.getPackageInfo(pkgName, GET_PERMISSIONS); + } catch (NameNotFoundException e) { + return; + } + + mAllUids.put(pkg.applicationInfo.uid, pkg.applicationInfo.uid); + + if (pkg.requestedPermissions == null) { + return; + } + + for (String permission : pkg.requestedPermissions) { final int opCode = AppOpsManager.permissionToOpCode(permission); if (opCode == AppOpsManager.OP_NONE) { continue; @@ -318,44 +464,63 @@ public final class PermissionPolicyService extends SystemService { final PermissionInfo permissionInfo; try { - permissionInfo = packageManager.getPermissionInfo(permission, 0); + permissionInfo = mPackageManager.getPermissionInfo(permission, 0); } catch (PackageManager.NameNotFoundException e) { continue; } - if (!permissionInfo.isRestricted()) { - continue; - } - - final boolean applyRestriction = PackageManager.RESTRICTED_PERMISSIONS_ENABLED - && (packageManager.getPermissionFlags(permission, pkg.packageName, - userHandle) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0; - - if (permissionInfo.isHardRestricted()) { - if (applyRestriction) { - mDefaultUidOps.put(opCode, uid); - } else { - mPackageNames.put(opCode, pkg.packageName); - mAllowedUidOps.put(opCode, uid); - } - } else if (permissionInfo.isSoftRestricted()) { - //TODO: Implement soft restrictions like storage here. - } + addOpIfRestricted(permissionInfo, pkg); + addOpIfFgPermissions(permissionInfo, pkg); } } - private static void setUidModeAllowed(@NonNull AppOpsManager appOpsManager, - int opCode, int uid, @NonNull String packageName) { - final int currentMode = appOpsManager.unsafeCheckOpRaw(AppOpsManager + private void setUidModeAllowed(int opCode, int uid, @NonNull String packageName) { + final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager .opToPublicName(opCode), uid, packageName); if (currentMode == AppOpsManager.MODE_DEFAULT) { - appOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_ALLOWED); + mAppOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_ALLOWED); } } - private static void setUidModeDefault(@NonNull AppOpsManager appOpsManager, - int opCode, int uid) { - appOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_DEFAULT); + private void setUidModeDefault(int opCode, int uid) { + mAppOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_DEFAULT); + } + + private class OpToRestrict { + final int uid; + final int code; + + OpToRestrict(int uid, int code) { + this.uid = uid; + this.code = code; + } + } + + private class OpToUnrestrict { + final int uid; + final @NonNull String packageName; + final int code; + + OpToUnrestrict(int uid, @NonNull String packageName, int code) { + this.uid = uid; + this.packageName = packageName; + this.code = code; + } + } + + private class FgPermission { + final int uid; + final @NonNull String packageName; + final @NonNull String fgPermissionName; + final @NonNull String bgPermissionName; + + private FgPermission(int uid, @NonNull String packageName, + @NonNull String fgPermissionName, @NonNull String bgPermissionName) { + this.uid = uid; + this.packageName = packageName; + this.fgPermissionName = fgPermissionName; + this.bgPermissionName = bgPermissionName; + } } } }