Merge changes from topic "DoNotCallAppOpsFromPermMananager" into qt-dev
* changes: Use PermissionPolicySve for fg perm app-ops Make perm policy synchronizer per user Make perm policy sve ready for additional usages
This commit is contained in:
committed by
Android (Google) Code Review
commit
0922770725
@@ -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<String> 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<String> 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;
|
||||
|
||||
@@ -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<String> 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<OpToRestrict> mOpsToRestrict = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* All ops that need to be unrestricted
|
||||
*
|
||||
* @see #syncRestrictedOps
|
||||
*/
|
||||
private final @NonNull ArrayList<OpToUnrestrict> mOpsToUnrestrict = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* All foreground permissions
|
||||
*
|
||||
* @see #syncOpsOfFgPermissions()
|
||||
*/
|
||||
private final @NonNull ArrayList<FgPermission> 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.
|
||||
*
|
||||
* <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
|
||||
@@ -222,52 +277,48 @@ public final class PermissionPolicyService extends SystemService {
|
||||
final SparseArray<List<String>> 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<String> 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<String> 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.
|
||||
*
|
||||
* <p>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}.
|
||||
*
|
||||
* <p>Note: Called with the package lock held. Do <u>not</u> 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.
|
||||
*
|
||||
* <p>Note: Called with the package lock held. Do <u>not</u> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user