Merge "Replace permission-specific methods with package change callback."
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 747ee3b..3139393 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -246,7 +246,6 @@
import android.graphics.Bitmap;
import android.hardware.display.DisplayManager;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -339,7 +338,6 @@
import com.android.internal.os.Zygote;
import com.android.internal.telephony.CarrierAppUtils;
import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.CollectionUtils;
import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
@@ -11592,22 +11590,6 @@
}
pkgSetting.signatures.mSigningDetails = reconciledPkg.signingDetails;
- if (!pkg.getAdoptPermissions().isEmpty()) {
- // This package wants to adopt ownership of permissions from
- // another package.
- for (int i = pkg.getAdoptPermissions().size() - 1; i >= 0; i--) {
- final String origName = pkg.getAdoptPermissions().get(i);
- final PackageSetting orig = mSettings.getPackageLPr(origName);
- if (orig != null) {
- if (verifyPackageUpdateLPr(orig, pkg)) {
- Slog.i(TAG, "Adopting permissions from " + origName + " to "
- + pkg.getPackageName());
- mPermissionManager.transferPermissions(origName, pkg.getPackageName());
- }
- }
- }
- }
-
if (changedAbiCodePath != null && changedAbiCodePath.size() > 0) {
for (int i = changedAbiCodePath.size() - 1; i >= 0; --i) {
final String codePathString = changedAbiCodePath.get(i);
@@ -12854,27 +12836,6 @@
reconciledPkg.prepareResult != null && reconciledPkg.prepareResult.replace;
mAppsFilter.addPackage(pkgSetting, isReplace);
- // Don't allow ephemeral applications to define new permissions groups.
- if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
- Slog.w(TAG, "Permission groups from package " + pkg.getPackageName()
- + " ignored: instant apps cannot define new permission groups.");
- } else {
- mPermissionManager.addAllPermissionGroups(pkg, chatty);
- }
-
- // If a permission has had its defining app changed, or it has had its protection
- // upgraded, we need to revoke apps that hold it
- final List<String> permissionsWithChangedDefinition;
- // Don't allow ephemeral applications to define new permissions.
- if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
- permissionsWithChangedDefinition = null;
- Slog.w(TAG, "Permissions from package " + pkg.getPackageName()
- + " ignored: instant apps cannot define new permissions.");
- } else {
- permissionsWithChangedDefinition =
- mPermissionManager.addAllPermissions(pkg, chatty);
- }
-
int collectionSize = ArrayUtils.size(pkg.getInstrumentations());
StringBuilder r = null;
int i;
@@ -12901,31 +12862,7 @@
}
}
- boolean hasOldPkg = oldPkg != null;
- boolean hasPermissionDefinitionChanges =
- !CollectionUtils.isEmpty(permissionsWithChangedDefinition);
- if (hasOldPkg || hasPermissionDefinitionChanges) {
- // We need to call revokeRuntimePermissionsIfGroupChanged async as permission
- // revoke callbacks from this method might need to kill apps which need the
- // mPackages lock on a different thread. This would dead lock.
- //
- // Hence create a copy of all package names and pass it into
- // revokeRuntimePermissionsIfGroupChanged. Only for those permissions might get
- // revoked. If a new package is added before the async code runs the permission
- // won't be granted yet, hence new packages are no problem.
- final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet());
-
- AsyncTask.execute(() -> {
- if (hasOldPkg) {
- mPermissionManager.revokeRuntimePermissionsIfGroupChanged(pkg, oldPkg,
- allPackageNames);
- }
- if (hasPermissionDefinitionChanges) {
- mPermissionManager.revokeRuntimePermissionsIfPermissionDefinitionChanged(
- permissionsWithChangedDefinition, allPackageNames);
- }
- });
- }
+ mPermissionManager.onPackageAdded(pkg, (scanFlags & SCAN_AS_INSTANT_APP) != 0, oldPkg);
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
diff --git a/services/core/java/com/android/server/pm/permission/Permission.java b/services/core/java/com/android/server/pm/permission/Permission.java
index 0245b28..687e96c 100644
--- a/services/core/java/com/android/server/pm/permission/Permission.java
+++ b/services/core/java/com/android/server/pm/permission/Permission.java
@@ -399,8 +399,7 @@
@NonNull
public static Permission createOrUpdate(@Nullable Permission permission,
@NonNull PermissionInfo permissionInfo, @NonNull AndroidPackage pkg,
- @NonNull Collection<Permission> permissionTrees, boolean isOverridingSystemPermission,
- boolean chatty) {
+ @NonNull Collection<Permission> permissionTrees, boolean isOverridingSystemPermission) {
// Allow system apps to redefine non-system permissions
boolean ownerChanged = false;
if (permission != null && !Objects.equals(permission.mPermissionInfo.packageName,
@@ -437,7 +436,7 @@
permission.mPermissionInfo = permissionInfo;
permission.mReconciled = true;
permission.mUid = pkg.getUid();
- if (chatty) {
+ if (PackageManagerService.DEBUG_PACKAGE_SCANNING) {
if (r == null) {
r = new StringBuilder(256);
} else {
@@ -456,7 +455,7 @@
+ permissionInfo.packageName + " ignored: original from "
+ permission.mPermissionInfo.packageName);
}
- } else if (chatty) {
+ } else if (PackageManagerService.DEBUG_PACKAGE_SCANNING) {
if (r == null) {
r = new StringBuilder(256);
} else {
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 6c03a28..092167d0 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -93,6 +93,7 @@
import android.content.pm.parsing.component.ParsedPermissionGroup;
import android.content.pm.permission.SplitPermissionInfoParcelable;
import android.metrics.LogMaker;
+import android.os.AsyncTask;
import android.os.Binder;
import android.os.Build;
import android.os.Debug;
@@ -133,6 +134,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.RoSystemProperties;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IntPair;
import com.android.internal.util.Preconditions;
@@ -2363,14 +2365,9 @@
*
* @param newPackage The new package that was installed
* @param oldPackage The old package that was updated
- * @param allPackageNames All package names
- * @param permissionCallback Callback for permission changed
*/
- private void revokeRuntimePermissionsIfGroupChanged(
- @NonNull AndroidPackage newPackage,
- @NonNull AndroidPackage oldPackage,
- @NonNull ArrayList<String> allPackageNames,
- @NonNull PermissionCallback permissionCallback) {
+ private void revokeRuntimePermissionsIfGroupChangedInternal(@NonNull AndroidPackage newPackage,
+ @NonNull AndroidPackage oldPackage) {
final int numOldPackagePermissions = ArrayUtils.size(oldPackage.getPermissions());
final ArrayMap<String, String> oldPermissionNameToGroupName
= new ArrayMap<>(numOldPackagePermissions);
@@ -2403,13 +2400,9 @@
if (newPermissionGroupName != null
&& !newPermissionGroupName.equals(oldPermissionGroupName)) {
final int[] userIds = mUserManagerInt.getUserIds();
- final int numUserIds = userIds.length;
- for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
- final int userId = userIds[userIdNum];
-
- final int numPackages = allPackageNames.size();
- for (int packageNum = 0; packageNum < numPackages; packageNum++) {
- final String packageName = allPackageNames.get(packageNum);
+ mPackageManagerInt.forEachPackage(pkg -> {
+ final String packageName = pkg.getPackageName();
+ for (final int userId : userIds) {
final int permissionState = checkPermission(permissionName, packageName,
userId);
if (permissionState == PackageManager.PERMISSION_GRANTED) {
@@ -2422,14 +2415,15 @@
try {
revokeRuntimePermissionInternal(permissionName, packageName,
- false, callingUid, userId, null, permissionCallback);
+ false, callingUid, userId, null,
+ mDefaultPermissionCallback);
} catch (IllegalArgumentException e) {
Slog.e(TAG, "Could not revoke " + permissionName + " from "
+ packageName, e);
}
}
}
- }
+ });
}
}
}
@@ -2440,18 +2434,11 @@
* granted permissions must be revoked.
*
* @param permissionsToRevoke A list of permission names to revoke
- * @param allPackageNames All package names
- * @param permissionCallback Callback for permission changed
*/
- private void revokeRuntimePermissionsIfPermissionDefinitionChanged(
- @NonNull List<String> permissionsToRevoke,
- @NonNull ArrayList<String> allPackageNames,
- @NonNull PermissionCallback permissionCallback) {
-
+ private void revokeRuntimePermissionsIfPermissionDefinitionChangedInternal(
+ @NonNull List<String> permissionsToRevoke) {
final int[] userIds = mUserManagerInt.getUserIds();
final int numPermissions = permissionsToRevoke.size();
- final int numUserIds = userIds.length;
- final int numPackages = allPackageNames.size();
final int callingUid = Binder.getCallingUid();
for (int permNum = 0; permNum < numPermissions; permNum++) {
@@ -2462,15 +2449,14 @@
continue;
}
}
- for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
- final int userId = userIds[userIdNum];
- for (int packageNum = 0; packageNum < numPackages; packageNum++) {
- final String packageName = allPackageNames.get(packageNum);
- final int uid = mPackageManagerInt.getPackageUid(packageName, 0, userId);
- if (uid < Process.FIRST_APPLICATION_UID) {
- // do not revoke from system apps
- continue;
- }
+ mPackageManagerInt.forEachPackage(pkg -> {
+ final String packageName = pkg.getPackageName();
+ final int appId = pkg.getUid();
+ if (appId < Process.FIRST_APPLICATION_UID) {
+ // do not revoke from system apps
+ return;
+ }
+ for (final int userId : userIds) {
final int permissionState = checkPermissionImpl(permName, packageName,
userId);
final int flags = getPermissionFlags(permName, packageName, userId);
@@ -2480,6 +2466,7 @@
| FLAG_PERMISSION_GRANTED_BY_ROLE;
if (permissionState == PackageManager.PERMISSION_GRANTED
&& (flags & flagMask) == 0) {
+ final int uid = UserHandle.getUid(userId, appId);
EventLog.writeEvent(0x534e4554, "154505240", uid,
"Revoking permission " + permName + " from package "
+ packageName + " due to definition change");
@@ -2490,18 +2477,18 @@
+ packageName + " due to definition change");
try {
revokeRuntimePermissionInternal(permName, packageName,
- false, callingUid, userId, null, permissionCallback);
+ false, callingUid, userId, null, mDefaultPermissionCallback);
} catch (Exception e) {
Slog.e(TAG, "Could not revoke " + permName + " from "
+ packageName, e);
}
}
}
- }
+ });
}
}
- private List<String> addAllPermissions(AndroidPackage pkg, boolean chatty) {
+ private List<String> addAllPermissionsInternal(@NonNull AndroidPackage pkg) {
final int N = ArrayUtils.size(pkg.getPermissions());
ArrayList<String> definitionChangedPermissions = new ArrayList<>();
for (int i=0; i<N; i++) {
@@ -2539,7 +2526,7 @@
synchronized (mLock) {
final Permission permission = Permission.createOrUpdate(oldPermission,
permissionInfo, pkg, mRegistry.getPermissionTrees(),
- isOverridingSystemPermission, chatty);
+ isOverridingSystemPermission);
if (p.isTree()) {
mRegistry.addPermissionTree(permission);
} else {
@@ -2557,7 +2544,7 @@
return definitionChangedPermissions;
}
- private void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) {
+ private void addAllPermissionGroupsInternal(@NonNull AndroidPackage pkg) {
synchronized (mLock) {
final int N = ArrayUtils.size(pkg.getPermissionGroups());
StringBuilder r = null;
@@ -2568,7 +2555,7 @@
final boolean isPackageUpdate = pg.getPackageName().equals(curPackageName);
if (cur == null || isPackageUpdate) {
mRegistry.addPermissionGroup(pg);
- if (chatty && DEBUG_PACKAGE_SCANNING) {
+ if (DEBUG_PACKAGE_SCANNING) {
if (r == null) {
r = new StringBuilder(256);
} else {
@@ -2583,7 +2570,7 @@
Slog.w(TAG, "Permission group " + pg.getName() + " from package "
+ pg.getPackageName() + " ignored: original from "
+ cur.getPackageName());
- if (chatty && DEBUG_PACKAGE_SCANNING) {
+ if (DEBUG_PACKAGE_SCANNING) {
if (r == null) {
r = new StringBuilder(256);
} else {
@@ -4848,11 +4835,81 @@
}
}
- private void transferPermissions(@NonNull String oldPackageName,
- @NonNull String newPackageName) {
- synchronized (mLock) {
- mRegistry.transferPermissions(oldPackageName, newPackageName);
+ private void onPackageAddedInternal(@NonNull AndroidPackage pkg, boolean isInstantApp,
+ @Nullable AndroidPackage oldPkg) {
+ if (!pkg.getAdoptPermissions().isEmpty()) {
+ // This package wants to adopt ownership of permissions from
+ // another package.
+ for (int i = pkg.getAdoptPermissions().size() - 1; i >= 0; i--) {
+ final String origName = pkg.getAdoptPermissions().get(i);
+ if (canAdoptPermissionsInternal(origName, pkg)) {
+ Slog.i(TAG, "Adopting permissions from " + origName + " to "
+ + pkg.getPackageName());
+ synchronized (mLock) {
+ mRegistry.transferPermissions(origName, pkg.getPackageName());
+ }
+ }
+ }
}
+
+ // Don't allow ephemeral applications to define new permissions groups.
+ if (isInstantApp) {
+ Slog.w(TAG, "Permission groups from package " + pkg.getPackageName()
+ + " ignored: instant apps cannot define new permission groups.");
+ } else {
+ addAllPermissionGroupsInternal(pkg);
+ }
+
+ // If a permission has had its defining app changed, or it has had its protection
+ // upgraded, we need to revoke apps that hold it
+ final List<String> permissionsWithChangedDefinition;
+ // Don't allow ephemeral applications to define new permissions.
+ if (isInstantApp) {
+ permissionsWithChangedDefinition = null;
+ Slog.w(TAG, "Permissions from package " + pkg.getPackageName()
+ + " ignored: instant apps cannot define new permissions.");
+ } else {
+ permissionsWithChangedDefinition = addAllPermissionsInternal(pkg);
+ }
+
+ boolean hasOldPkg = oldPkg != null;
+ boolean hasPermissionDefinitionChanges =
+ !CollectionUtils.isEmpty(permissionsWithChangedDefinition);
+ if (hasOldPkg || hasPermissionDefinitionChanges) {
+ // We need to call revokeRuntimePermissionsIfGroupChanged async as permission
+ // revoke callbacks from this method might need to kill apps which need the
+ // mPackages lock on a different thread. This would dead lock.
+ AsyncTask.execute(() -> {
+ if (hasOldPkg) {
+ revokeRuntimePermissionsIfGroupChangedInternal(pkg, oldPkg);
+ }
+ if (hasPermissionDefinitionChanges) {
+ revokeRuntimePermissionsIfPermissionDefinitionChangedInternal(
+ permissionsWithChangedDefinition);
+ }
+ });
+ }
+ }
+
+ private boolean canAdoptPermissionsInternal(@NonNull String oldPackageName,
+ @NonNull AndroidPackage newPkg) {
+ final PackageSetting oldPs = mPackageManagerInt.getPackageSetting(oldPackageName);
+ if (oldPs == null) {
+ return false;
+ }
+ if (!oldPs.isSystem()) {
+ Slog.w(TAG, "Unable to update from " + oldPs.name
+ + " to " + newPkg.getPackageName()
+ + ": old package not in system partition");
+ return false;
+ }
+ if (mPackageManagerInt.getPackage(oldPs.name) != null) {
+ Slog.w(TAG, "Unable to update from " + oldPs.name
+ + " to " + newPkg.getPackageName()
+ + ": old package still exists");
+ return false;
+ }
+ return true;
}
private boolean canPropagatePermissionToInstantApp(@NonNull String permissionName) {
@@ -4955,31 +5012,6 @@
}
@Override
- public void revokeRuntimePermissionsIfGroupChanged(
- @NonNull AndroidPackage newPackage,
- @NonNull AndroidPackage oldPackage,
- @NonNull ArrayList<String> allPackageNames) {
- PermissionManagerService.this.revokeRuntimePermissionsIfGroupChanged(newPackage,
- oldPackage, allPackageNames, mDefaultPermissionCallback);
- }
-
- @Override
- public void revokeRuntimePermissionsIfPermissionDefinitionChanged(
- @NonNull List<String> permissionsToRevoke,
- @NonNull ArrayList<String> allPackageNames) {
- PermissionManagerService.this.revokeRuntimePermissionsIfPermissionDefinitionChanged(
- permissionsToRevoke, allPackageNames, mDefaultPermissionCallback);
- }
-
- @Override
- public List<String> addAllPermissions(AndroidPackage pkg, boolean chatty) {
- return PermissionManagerService.this.addAllPermissions(pkg, chatty);
- }
- @Override
- public void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) {
- PermissionManagerService.this.addAllPermissionGroups(pkg, chatty);
- }
- @Override
public void removeAllPermissions(AndroidPackage pkg, boolean chatty) {
PermissionManagerService.this.removeAllPermissions(pkg, chatty);
}
@@ -5313,9 +5345,10 @@
}
@Override
- public void transferPermissions(@NonNull String oldPackageName,
- @NonNull String newPackageName) {
- PermissionManagerService.this.transferPermissions(oldPackageName, newPackageName);
+ public void onPackageAdded(@NonNull AndroidPackage pkg, boolean isInstantApp,
+ @Nullable AndroidPackage oldPkg) {
+ Objects.requireNonNull(pkg);
+ onPackageAddedInternal(pkg, isInstantApp, oldPkg);
}
@Override
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index df9d0d3..11b6f31 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -276,42 +276,6 @@
//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
public abstract void resetAllRuntimePermissions(@UserIdInt int userId);
- /**
- * We might auto-grant permissions if any permission of the group is already granted. Hence if
- * the group of a granted permission changes we need to revoke it to avoid having permissions of
- * the new group auto-granted.
- *
- * @param newPackage The new package that was installed
- * @param oldPackage The old package that was updated
- * @param allPackageNames All packages
- */
- public abstract void revokeRuntimePermissionsIfGroupChanged(
- @NonNull AndroidPackage newPackage,
- @NonNull AndroidPackage oldPackage,
- @NonNull ArrayList<String> allPackageNames);
-
- /**
- * Some permissions might have been owned by a non-system package, and the system then defined
- * said permission. Some other permissions may one have been install permissions, but are now
- * runtime or higher. These permissions should be revoked.
- *
- * @param permissionsToRevoke A list of permission names to revoke
- * @param allPackageNames All packages
- */
- public abstract void revokeRuntimePermissionsIfPermissionDefinitionChanged(
- @NonNull List<String> permissionsToRevoke,
- @NonNull ArrayList<String> allPackageNames);
-
- /**
- * Add all permissions in the given package.
- * <p>
- * NOTE: argument {@code groupTEMP} is temporary until mPermissionGroups is moved to
- * the permission settings.
- *
- * @return A list of BasePermissions that were updated, and need to be revoked from packages
- */
- public abstract List<String> addAllPermissions(@NonNull AndroidPackage pkg, boolean chatty);
- public abstract void addAllPermissionGroups(@NonNull AndroidPackage pkg, boolean chatty);
public abstract void removeAllPermissions(@NonNull AndroidPackage pkg, boolean chatty);
/**
@@ -578,10 +542,15 @@
@NonNull LegacyPermissionSettings legacyPermissionSettings);
/**
- * Transfers ownership of permissions from one package to another.
+ * Callback when a package has been added.
+ *
+ * @param pkg the added package
+ * @param isInstantApp whether the added package is an instant app
+ * @param oldPkg the old package, or {@code null} if none
*/
- public abstract void transferPermissions(@NonNull String oldPackageName,
- @NonNull String newPackageName);
+ //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+ public abstract void onPackageAdded(@NonNull AndroidPackage pkg, boolean isInstantApp,
+ @Nullable AndroidPackage oldPkg);
/**
* Check whether a permission can be propagated to instant app.