diff options
-rw-r--r-- | services/core/java/com/android/server/policy/PermissionPolicyService.java | 220 |
1 files changed, 95 insertions, 125 deletions
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java index c13cb38544c5..ec8e1a05852e 100644 --- a/services/core/java/com/android/server/policy/PermissionPolicyService.java +++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java @@ -39,7 +39,9 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManagerInternal.PackageListObserver; import android.content.pm.PermissionInfo; +import android.content.pm.parsing.AndroidPackage; import android.os.Build; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; @@ -50,15 +52,14 @@ import android.telecom.TelecomManager; import android.util.ArrayMap; import android.util.ArraySet; import android.util.LongSparseLongArray; +import android.util.Pair; import android.util.Slog; -import android.util.SparseArray; import android.util.SparseBooleanArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IAppOpsCallback; import com.android.internal.app.IAppOpsService; import com.android.internal.infra.AndroidFuture; -import com.android.internal.util.ArrayUtils; import com.android.internal.util.IntPair; import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.FgThread; @@ -69,7 +70,6 @@ import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback; import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.concurrent.ExecutionException; /** @@ -100,7 +100,7 @@ public final class PermissionPolicyService extends SystemService { * scheduled for a package/user. */ @GuardedBy("mLock") - private final ArraySet<Integer> mIsPackageSyncsScheduled = new ArraySet<>(); + private final ArraySet<Pair<String, Integer>> mIsPackageSyncsScheduled = new ArraySet<>(); public PermissionPolicyService(@NonNull Context context) { super(context); @@ -125,8 +125,10 @@ public final class PermissionPolicyService extends SystemService { @Override public void onPackageChanged(String packageName, int uid) { - if (isStarted(UserHandle.getUserId(uid))) { - synchronizePackagePermissionsAndAppOpsForUser(uid); + final int userId = UserHandle.getUserId(uid); + + if (isStarted(userId)) { + synchronizePackagePermissionsAndAppOpsForUser(packageName, userId); } } @@ -137,21 +139,12 @@ public final class PermissionPolicyService extends SystemService { }); permManagerInternal.addOnRuntimePermissionStateChangedListener( - (packageName, userId) -> { - int uid; - try { - uid = getContext().getPackageManager().getPackageUidAsUser(packageName, 0, - userId); - } catch (NameNotFoundException e) { - Slog.e(LOG_TAG, "Cannot synchronize changed package " + packageName, e); - return; - } - synchronizeUidPermissionsAndAppOpsAsync(uid); - }); + this::synchronizePackagePermissionsAndAppOpsAsyncForUser); mAppOpsCallback = new IAppOpsCallback.Stub() { public void opChanged(int op, int uid, String packageName) { - synchronizeUidPermissionsAndAppOpsAsync(uid); + synchronizePackagePermissionsAndAppOpsAsyncForUser(packageName, + UserHandle.getUserId(uid)); } }; @@ -201,17 +194,19 @@ public final class PermissionPolicyService extends SystemService { return AppOpsManager.opToSwitch(op); } - private void synchronizeUidPermissionsAndAppOpsAsync(int uid) { - if (isStarted(UserHandle.getUserId(uid))) { + private void synchronizePackagePermissionsAndAppOpsAsyncForUser(@NonNull String packageName, + @UserIdInt int changedUserId) { + if (isStarted(changedUserId)) { synchronized (mLock) { - if (mIsPackageSyncsScheduled.add(uid)) { + if (mIsPackageSyncsScheduled.add(new Pair<>(packageName, changedUserId))) { FgThread.getHandler().sendMessage(PooledLambda.obtainMessage( PermissionPolicyService ::synchronizePackagePermissionsAndAppOpsForUser, - this, uid)); + this, packageName, changedUserId)); } else { if (DEBUG) { - Slog.v(LOG_TAG, "sync for " + uid + " already scheduled"); + Slog.v(LOG_TAG, "sync for " + packageName + "/" + changedUserId + + " already scheduled"); } } } @@ -340,20 +335,39 @@ public final class PermissionPolicyService extends SystemService { /** * Synchronize a single package. */ - private void synchronizePackagePermissionsAndAppOpsForUser(int uid) { + private void synchronizePackagePermissionsAndAppOpsForUser(@NonNull String packageName, + @UserIdInt int userId) { synchronized (mLock) { - mIsPackageSyncsScheduled.remove(uid); + mIsPackageSyncsScheduled.remove(new Pair<>(packageName, userId)); } if (DEBUG) { Slog.v(LOG_TAG, - "synchronizePackagePermissionsAndAppOpsForUser(" + uid + ")"); + "synchronizePackagePermissionsAndAppOpsForUser(" + packageName + ", " + + userId + ")"); } + final PackageManagerInternal packageManagerInternal = LocalServices.getService( + PackageManagerInternal.class); + final PackageInfo pkg = packageManagerInternal.getPackageInfo(packageName, 0, + Process.SYSTEM_UID, userId); + if (pkg == null) { + return; + } final PermissionToOpSynchroniser synchroniser = new PermissionToOpSynchroniser( - getUserContext(getContext(), UserHandle.getUserHandleForUid(uid))); - synchroniser.addUid(uid); - synchroniser.syncUids(); + getUserContext(getContext(), UserHandle.of(userId))); + synchroniser.addPackage(pkg.packageName); + final String[] sharedPkgNames = packageManagerInternal.getSharedUserPackagesForPackage( + pkg.packageName, userId); + + for (String sharedPkgName : sharedPkgNames) { + final AndroidPackage sharedPkg = packageManagerInternal + .getPackage(sharedPkgName); + if (sharedPkg != null) { + synchroniser.addPackage(sharedPkg.getPackageName()); + } + } + synchroniser.syncPackages(); } /** @@ -367,8 +381,8 @@ public final class PermissionPolicyService extends SystemService { final PermissionToOpSynchroniser synchronizer = new PermissionToOpSynchroniser( getUserContext(getContext(), UserHandle.of(userId))); packageManagerInternal.forEachPackage( - (pkg) -> synchronizer.addUid(pkg.getUid())); - synchronizer.syncUids(); + (pkg) -> synchronizer.addPackage(pkg.getPackageName())); + synchronizer.syncPackages(); } /** @@ -383,51 +397,37 @@ public final class PermissionPolicyService extends SystemService { private final @NonNull ArrayMap<String, PermissionInfo> mRuntimePermissionInfos; - // Cache uid -> packageNames - private SparseArray<String[]> mUidToPkg = new SparseArray<>(); - /** * All ops that need to be flipped to allow. * - * @see #syncUids + * @see #syncPackages */ - private final @NonNull ArraySet<OpToChange> mOpsToAllow = new ArraySet<>(); + private final @NonNull ArrayList<OpToChange> mOpsToAllow = new ArrayList<>(); /** * All ops that need to be flipped to ignore. * - * @see #syncUids + * @see #syncPackages */ - private final @NonNull ArraySet<OpToChange> mOpsToIgnore = new ArraySet<>(); + 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 #syncUids + * @see #syncPackages */ - private final @NonNull ArraySet<OpToChange> mOpsToIgnoreIfNotAllowed = new ArraySet<>(); + 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. * - * @see #syncUids + * @see #syncPackages */ - private final @NonNull ArraySet<OpToChange> mOpsToForeground = new ArraySet<>(); - - private @Nullable String[] getPackageNamesForUid(int uid) { - String[] pkgs = mUidToPkg.get(uid); - if (pkgs != null) { - return pkgs; - } - - pkgs = mPackageManager.getPackagesForUid(uid); - mUidToPkg.put(uid, pkgs); - return pkgs; - } + private final @NonNull ArrayList<OpToChange> mOpsToForeground = new ArrayList<>(); PermissionToOpSynchroniser(@NonNull Context context) { mContext = context; @@ -449,11 +449,11 @@ public final class PermissionPolicyService extends SystemService { } /** - * Set app ops that were added in {@link #addUid}. + * Set app ops that were added in {@link #addPackage}. * * <p>This processes ops previously added by {@link #addAppOps(PackageInfo, String)} */ - private void syncUids() { + private void syncPackages() { // Remember which ops were already set. This makes sure that we always set the most // permissive mode if two OpChanges are scheduled. This can e.g. happen if two // permissions change the same op. See {@link #getSwitchOp}. @@ -461,42 +461,42 @@ public final class PermissionPolicyService extends SystemService { final int allowCount = mOpsToAllow.size(); for (int i = 0; i < allowCount; i++) { - final OpToChange op = mOpsToAllow.valueAt(i); + final OpToChange op = mOpsToAllow.get(i); - setUidModeAllowed(op.code, op.uid); + setUidModeAllowed(op.code, op.uid, op.packageName); alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1); } final int foregroundCount = mOpsToForeground.size(); for (int i = 0; i < foregroundCount; i++) { - final OpToChange op = mOpsToForeground.valueAt(i); + final OpToChange op = mOpsToForeground.get(i); if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) { continue; } - setUidModeForeground(op.code, op.uid); + setUidModeForeground(op.code, op.uid, op.packageName); alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1); } final int ignoreCount = mOpsToIgnore.size(); for (int i = 0; i < ignoreCount; i++) { - final OpToChange op = mOpsToIgnore.valueAt(i); + final OpToChange op = mOpsToIgnore.get(i); if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) { continue; } - setUidModeIgnored(op.code, op.uid); + setUidModeIgnored(op.code, op.uid, op.packageName); alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1); } final int ignoreIfNotAllowedCount = mOpsToIgnoreIfNotAllowed.size(); for (int i = 0; i < ignoreIfNotAllowedCount; i++) { - final OpToChange op = mOpsToIgnoreIfNotAllowed.valueAt(i); + final OpToChange op = mOpsToIgnoreIfNotAllowed.get(i); if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) { continue; } - boolean wasSet = setUidModeIgnoredIfNotAllowed(op.code, op.uid); + boolean wasSet = setUidModeIgnoredIfNotAllowed(op.code, op.uid, op.packageName); if (wasSet) { alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1); } @@ -555,7 +555,7 @@ public final class PermissionPolicyService extends SystemService { } int uid = packageInfo.applicationInfo.uid; - OpToChange opToChange = new OpToChange(uid, appOpCode); + OpToChange opToChange = new OpToChange(uid, packageName, appOpCode); switch (appOpMode) { case MODE_ALLOWED: mOpsToAllow.add(opToChange); @@ -618,7 +618,8 @@ public final class PermissionPolicyService extends SystemService { } int uid = packageInfo.applicationInfo.uid; - OpToChange extraOpToChange = new OpToChange(uid, extraOpCode); + String packageName = packageInfo.packageName; + OpToChange extraOpToChange = new OpToChange(uid, packageName, extraOpCode); if (policy.mayAllowExtraAppOp()) { mOpsToAllow.add(extraOpToChange); } else { @@ -631,56 +632,45 @@ public final class PermissionPolicyService extends SystemService { } /** - * Add a Uid for {@link #syncUids() processing} later. + * 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 uid The uid to add for later processing. + * @param pkgName The package to add for later processing. */ - void addUid(int uid) { - String[] pkgNames = getPackageNamesForUid(uid); - if (pkgNames == null) { + void addPackage(@NonNull String pkgName) { + final PackageInfo pkg; + try { + pkg = mPackageManager.getPackageInfo(pkgName, GET_PERMISSIONS); + } catch (NameNotFoundException e) { return; } - for (String pkgName : pkgNames) { - final PackageInfo pkg; - try { - pkg = mPackageManager.getPackageInfo(pkgName, GET_PERMISSIONS); - } catch (NameNotFoundException e) { - continue; - } - - if (pkg.requestedPermissions == null) { - continue; - } + if (pkg.requestedPermissions == null) { + return; + } - for (String permission : pkg.requestedPermissions) { - addAppOps(pkg, permission); - } + for (String permission : pkg.requestedPermissions) { + addAppOps(pkg, permission); } } - private void setUidModeAllowed(int opCode, int uid) { - setUidMode(opCode, uid, MODE_ALLOWED); + private void setUidModeAllowed(int opCode, int uid, @NonNull String packageName) { + setUidMode(opCode, uid, MODE_ALLOWED, packageName); } - private void setUidModeForeground(int opCode, int uid) { - setUidMode(opCode, uid, MODE_FOREGROUND); + private void setUidModeForeground(int opCode, int uid, @NonNull String packageName) { + setUidMode(opCode, uid, MODE_FOREGROUND, packageName); } - private void setUidModeIgnored(int opCode, int uid) { - setUidMode(opCode, uid, MODE_IGNORED); + private void setUidModeIgnored(int opCode, int uid, @NonNull String packageName) { + setUidMode(opCode, uid, MODE_IGNORED, packageName); } - private boolean setUidModeIgnoredIfNotAllowed(int opCode, int uid) { - String[] pkgsOfUid = getPackageNamesForUid(uid); - if (ArrayUtils.isEmpty(pkgsOfUid)) { - return false; - } - + private boolean setUidModeIgnoredIfNotAllowed(int opCode, int uid, + @NonNull String packageName) { final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName( - opCode), uid, pkgsOfUid[0]); + opCode), uid, packageName); if (currentMode != MODE_ALLOWED) { if (currentMode != MODE_IGNORED) { mAppOpsManagerInternal.setUidModeFromPermissionPolicy(opCode, uid, MODE_IGNORED, @@ -691,24 +681,20 @@ public final class PermissionPolicyService extends SystemService { return false; } - private void setUidMode(int opCode, int uid, int mode) { - String[] pkgsOfUid = getPackageNamesForUid(uid); - if (ArrayUtils.isEmpty(pkgsOfUid)) { - return; - } - + private void setUidMode(int opCode, int uid, int mode, + @NonNull String packageName) { final int oldMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName( - opCode), uid, pkgsOfUid[0]); + opCode), uid, packageName); if (oldMode != mode) { mAppOpsManagerInternal.setUidModeFromPermissionPolicy(opCode, uid, mode, mAppOpsCallback); final int newMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName( - opCode), uid, pkgsOfUid[0]); + opCode), uid, packageName); if (newMode != mode) { // Work around incorrectly-set package mode. It never makes sense for app ops // related to runtime permissions, but can get in the way and we have to reset // it. - mAppOpsManagerInternal.setModeFromPermissionPolicy(opCode, uid, pkgsOfUid[0], + mAppOpsManagerInternal.setModeFromPermissionPolicy(opCode, uid, packageName, AppOpsManager.opToDefaultMode(opCode), mAppOpsCallback); } } @@ -716,30 +702,14 @@ public final class PermissionPolicyService extends SystemService { private class OpToChange { final int uid; + final @NonNull String packageName; final int code; - OpToChange(int uid, int code) { + OpToChange(int uid, @NonNull String packageName, int code) { this.uid = uid; + this.packageName = packageName; this.code = code; } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - OpToChange other = (OpToChange) o; - return uid == other.uid && code == other.code; - } - - @Override - public int hashCode() { - return Objects.hash(uid, code); - } } } |