Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 44e16cd5 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Replace permission-specific methods with package change callback."

parents d6b491aa 059333b3
Loading
Loading
Loading
Loading
+1 −64
Original line number Diff line number Diff line
@@ -246,7 +246,6 @@ import android.database.ContentObserver;
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.SomeArgs;
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 @@ public class PackageManagerService extends IPackageManager.Stub
        }
        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 @@ public class PackageManagerService extends IPackageManager.Stub
                    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 @@ public class PackageManagerService extends IPackageManager.Stub
                }
            }
            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);
+3 −4
Original line number Diff line number Diff line
@@ -399,8 +399,7 @@ public final class Permission {
    @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 @@ public final class Permission {
                    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 @@ public final class Permission {
                        + 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 {
+106 −73
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@ import android.content.pm.parsing.component.ParsedPermission;
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.MetricsLogger;
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 @@ public class PermissionManagerService extends IPermissionManager.Stub {
     *
     * @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 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                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 @@ public class PermissionManagerService extends IPermissionManager.Stub {

                                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 @@ public class PermissionManagerService extends IPermissionManager.Stub {
     * 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 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                    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) {
            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
                        continue;
                    return;
                }
                for (final int userId : userIds) {
                    final int permissionState = checkPermissionImpl(permName, packageName,
                            userId);
                    final int flags = getPermissionFlags(permName, packageName, userId);
@@ -2480,6 +2466,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                            | 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 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                                + 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 @@ public class PermissionManagerService extends IPermissionManager.Stub {
            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 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        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 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                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 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                    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,13 +4835,83 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        }
    }

    private void transferPermissions(@NonNull String oldPackageName,
            @NonNull String 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(oldPackageName, newPackageName);
                        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) {
        synchronized (mLock) {
            final Permission bp = mRegistry.getPermission(permissionName);
@@ -4954,31 +5011,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
            return isPermissionsReviewRequiredInternal(packageName, userId);
        }

        @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 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        }

        @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
+8 −39
Original line number Diff line number Diff line
@@ -276,42 +276,6 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
    //@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 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
            @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.