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

Commit dc65aa3f authored by Philip P. Moltmann's avatar Philip P. Moltmann
Browse files

Refactor updatePermissions path

- Give the methods more descriptive names
- Reduce the number of paramters
- Add comments

No functional change

Test: Built
      atest --test-mapping frameworks/base/services/core/java/com/android/server/pm/permission:presubmit
Change-Id: I2fdf5bf7a0223604512307f26ad4881fde913873
parent d89ba639
Loading
Loading
Loading
Loading
+4 −5
Original line number Original line Diff line number Diff line
@@ -3368,8 +3368,7 @@ public class PackageManagerService extends IPackageManager.Stub
                    } catch (PackageManagerException e) {
                    } catch (PackageManagerException e) {
                        Slog.e(TAG, "updateAllSharedLibrariesLPw failed: ", e);
                        Slog.e(TAG, "updateAllSharedLibrariesLPw failed: ", e);
                    }
                    }
                    mPermissionManager.updatePermissions(
                    mPermissionManager.updatePermissions(pkg.packageName, pkg, mPackages.values(),
                            pkg.packageName, pkg, true, mPackages.values(),
                            mPermissionCallback);
                            mPermissionCallback);
                    mSettings.writeLPr();
                    mSettings.writeLPr();
                }
                }
@@ -15984,7 +15983,7 @@ public class PackageManagerService extends IPackageManager.Stub
        if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.codePath);
        if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.codePath);
        synchronized (mPackages) {
        synchronized (mPackages) {
// NOTE: This changes slightly to include UPDATE_PERMISSIONS_ALL regardless of the size of pkg.permissions
// NOTE: This changes slightly to include UPDATE_PERMISSIONS_ALL regardless of the size of pkg.permissions
            mPermissionManager.updatePermissions(pkg.packageName, pkg, true, mPackages.values(),
            mPermissionManager.updatePermissions(pkg.packageName, pkg, mPackages.values(),
                    mPermissionCallback);
                    mPermissionCallback);
            // For system-bundled packages, we assume that installing an upgraded version
            // For system-bundled packages, we assume that installing an upgraded version
            // of the package implies that the user actually wants to run that new code,
            // of the package implies that the user actually wants to run that new code,
@@ -18637,7 +18636,7 @@ public class PackageManagerService extends IPackageManager.Stub
                        outInfo.removedAppId = removedAppId;
                        outInfo.removedAppId = removedAppId;
                    }
                    }
                    mPermissionManager.updatePermissions(
                    mPermissionManager.updatePermissions(
                            deletedPs.name, null, false, mPackages.values(), mPermissionCallback);
                            deletedPs.name, null, mPackages.values(), mPermissionCallback);
                    if (deletedPs.sharedUser != null) {
                    if (deletedPs.sharedUser != null) {
                        // Remove permissions associated with package. Since runtime
                        // Remove permissions associated with package. Since runtime
                        // permissions are per user we have to kill the removed package
                        // permissions are per user we have to kill the removed package
@@ -18916,7 +18915,7 @@ public class PackageManagerService extends IPackageManager.Stub
            if (origPermissionState != null) {
            if (origPermissionState != null) {
                ps.getPermissionsState().copyFrom(origPermissionState);
                ps.getPermissionsState().copyFrom(origPermissionState);
            }
            }
            mPermissionManager.updatePermissions(pkg.packageName, pkg, true, mPackages.values(),
            mPermissionManager.updatePermissions(pkg.packageName, pkg, mPackages.values(),
                    mPermissionCallback);
                    mPermissionCallback);
            final boolean applyUserRestrictions
            final boolean applyUserRestrictions
+176 −48
Original line number Original line Diff line number Diff line
@@ -45,6 +45,7 @@ import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERA
import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;


import android.Manifest;
import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.annotation.UserIdInt;
@@ -102,6 +103,8 @@ import com.android.server.pm.permission.PermissionsState.PermissionState;


import libcore.util.EmptyArray;
import libcore.util.EmptyArray;


import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashMap;
@@ -2439,15 +2442,24 @@ public class PermissionManagerService {
        return permissionsState.getPermissionFlags(permName, userId);
        return permissionsState.getPermissionFlags(permName, userId);
    }
    }


    private static final int UPDATE_PERMISSIONS_ALL = 1<<0;
    /**
    private static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1<<1;
     * Update permissions when a package changed.
    private static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1<<2;
     *

     * <p><ol>
    private void updatePermissions(String packageName, PackageParser.Package pkg,
     *     <li>Reconsider the ownership of permission</li>
            boolean replaceGrant, Collection<PackageParser.Package> allPackages,
     *     <li>Update the state (grant, flags) of the permissions</li>
            PermissionCallback callback) {
     * </ol>
        final int flags = (pkg != null ? UPDATE_PERMISSIONS_ALL : 0) |
     *
                (replaceGrant ? UPDATE_PERMISSIONS_REPLACE_PKG : 0);
     * @param packageName The package that is updated
     * @param pkg The package that is updated, or {@code null} if package is deleted
     * @param allPackages All currently known packages
     * @param callback Callback to call after permission changes
     */
    private void updatePermissions(@NonNull String packageName, @Nullable PackageParser.Package pkg,
            @NonNull Collection<PackageParser.Package> allPackages,
            @NonNull PermissionCallback callback) {
        final int flags =
                (pkg != null ? UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG : 0);
        updatePermissions(
        updatePermissions(
                packageName, pkg, getVolumeUuidForPackage(pkg), flags, allPackages, callback);
                packageName, pkg, getVolumeUuidForPackage(pkg), flags, allPackages, callback);
        if (pkg != null && pkg.childPackages != null) {
        if (pkg != null && pkg.childPackages != null) {
@@ -2458,8 +2470,21 @@ public class PermissionManagerService {
        }
        }
    }
    }


    private void updateAllPermissions(String volumeUuid, boolean sdkUpdated,
    /**
            Collection<PackageParser.Package> allPackages, PermissionCallback callback) {
     * Update all permissions for all apps.
     *
     * <p><ol>
     *     <li>Reconsider the ownership of permission</li>
     *     <li>Update the state (grant, flags) of the permissions</li>
     * </ol>
     *
     * @param volumeUuid The volume of the packages to be updated, {@code null} for all volumes
     * @param allPackages All currently known packages
     * @param callback Callback to call after permission changes
     */
    private void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdated,
            @NonNull Collection<PackageParser.Package> allPackages,
            @NonNull PermissionCallback callback) {
        final int flags = UPDATE_PERMISSIONS_ALL |
        final int flags = UPDATE_PERMISSIONS_ALL |
                (sdkUpdated
                (sdkUpdated
                        ? UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL
                        ? UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL
@@ -2467,25 +2492,12 @@ public class PermissionManagerService {
        updatePermissions(null, null, volumeUuid, flags, allPackages, callback);
        updatePermissions(null, null, volumeUuid, flags, allPackages, callback);
    }
    }


    private void updatePermissions(String changingPkgName, PackageParser.Package changingPkg,
    /**
            String replaceVolumeUuid, int flags, Collection<PackageParser.Package> allPackages,
     * Cache background->foreground permission mapping.
            PermissionCallback callback) {
     *
        // TODO: Most of the methods exposing BasePermission internals [source package name,
     * <p>This is only run once.
        // etc..] shouldn't be needed. Instead, when we've parsed a permission that doesn't
     */
        // have package settings, we should make note of it elsewhere [map between
    private void cacheBackgroundToForegoundPermissionMapping() {
        // source package name and BasePermission] and cycle through that here. Then we
        // define a single method on BasePermission that takes a PackageSetting, changing
        // package name and a package.
        // NOTE: With this approach, we also don't need to tree trees differently than
        // normal permissions. Today, we need two separate loops because these BasePermission
        // objects are stored separately.
        // Make sure there are no dangling permission trees.
        flags = updatePermissionTrees(changingPkgName, changingPkg, flags);

        // Make sure all dynamic permissions have been assigned to a package,
        // and make sure there are no dangling permissions.
        flags = updatePermissions(changingPkgName, changingPkg, flags);

        synchronized (mLock) {
        synchronized (mLock) {
            if (mBackgroundPermissions == null) {
            if (mBackgroundPermissions == null) {
                // Cache background -> foreground permission mapping.
                // Cache background -> foreground permission mapping.
@@ -2508,10 +2520,85 @@ public class PermissionManagerService {
                }
                }
            }
            }
        }
        }
    }

    /**
     * Update all packages on the volume, <u>beside</u> the changing package. If the changing
     * package is set too, all packages are updated.
     */
    private static final int UPDATE_PERMISSIONS_ALL = 1 << 0;
    /** The changing package is replaced. Requires the changing package to be set */
    private static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1 << 1;
    /**
     * Schedule all packages <u>beside</u> the changing package for replacement. Requires
     * UPDATE_PERMISSIONS_ALL to be set
     */
    private static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1 << 2;

    @IntDef(flag = true, prefix = { "UPDATE_PERMISSIONS_" }, value = {
            UPDATE_PERMISSIONS_ALL, UPDATE_PERMISSIONS_REPLACE_PKG,
            UPDATE_PERMISSIONS_REPLACE_ALL })
    @Retention(RetentionPolicy.SOURCE)
    private @interface UpdatePermissionFlags {}

    /**
     * Update permissions when packages changed.
     *
     * <p><ol>
     *     <li>Reconsider the ownership of permission</li>
     *     <li>Update the state (grant, flags) of the permissions</li>
     * </ol>
     *
     * <p>Meaning of combination of package parameters:
     * <table>
     *     <tr><th></th><th>changingPkgName != null</th><th>changingPkgName == null</th></tr>
     *     <tr><th>changingPkg != null</th><td>package is updated</td><td>invalid</td></tr>
     *     <tr><th>changingPkg == null</th><td>package is deleted</td><td>all packages are
     *                                                                    updated</td></tr>
     * </table>
     *
     * @param changingPkgName The package that is updated, or {@code null} if all packages should be
     *                    updated
     * @param changingPkg The package that is updated, or {@code null} if all packages should be
     *                    updated or package is deleted
     * @param replaceVolumeUuid The volume of the packages to be updated are on, {@code null} for
     *                          all volumes
     * @param flags Control permission for which apps should be updated
     * @param allPackages All currently known packages
     * @param callback Callback to call after permission changes
     */
    private void updatePermissions(@Nullable String changingPkgName,
            @Nullable PackageParser.Package changingPkg, @Nullable String replaceVolumeUuid,
            @UpdatePermissionFlags int flags,
            @NonNull Collection<PackageParser.Package> allPackages,
            @Nullable PermissionCallback callback) {
        // TODO: Most of the methods exposing BasePermission internals [source package name,
        // etc..] shouldn't be needed. Instead, when we've parsed a permission that doesn't
        // have package settings, we should make note of it elsewhere [map between
        // source package name and BasePermission] and cycle through that here. Then we
        // define a single method on BasePermission that takes a PackageSetting, changing
        // package name and a package.
        // NOTE: With this approach, we also don't need to tree trees differently than
        // normal permissions. Today, we need two separate loops because these BasePermission
        // objects are stored separately.
        // Make sure there are no dangling permission trees.
        boolean permissionTreesSourcePackageChanged = updatePermissionTreeSourcePackage(
                changingPkgName, changingPkg);
        // Make sure all dynamic permissions have been assigned to a package,
        // and make sure there are no dangling permissions.
        boolean permissionSourcePackageChanged = updatePermissionSourcePackage(changingPkgName,
                changingPkg);

        if (permissionTreesSourcePackageChanged | permissionSourcePackageChanged) {
            // Permission ownership has changed. This e.g. changes which packages can get signature
            // permissions
            flags |= UPDATE_PERMISSIONS_ALL;
        }

        cacheBackgroundToForegoundPermissionMapping();


        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "restorePermissionState");
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "restorePermissionState");
        // Now update the permissions for all packages, in particular
        // Now update the permissions for all packages.
        // replace the granted permissions of the system packages.
        if ((flags & UPDATE_PERMISSIONS_ALL) != 0) {
        if ((flags & UPDATE_PERMISSIONS_ALL) != 0) {
            for (PackageParser.Package pkg : allPackages) {
            for (PackageParser.Package pkg : allPackages) {
                if (pkg != changingPkg) {
                if (pkg != changingPkg) {
@@ -2534,7 +2621,27 @@ public class PermissionManagerService {
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }
    }


    private int updatePermissions(String packageName, PackageParser.Package pkg, int flags) {
    /**
     * Update which app declares a permission.
     *
     * <p>Possible parameter combinations
     * <table>
     *     <tr><th></th><th>packageName != null</th><th>packageName == null</th></tr>
     *     <tr><th>pkg != null</th><td>package is updated</td><td>invalid</td></tr>
     *     <tr><th>pkg == null</th><td>package is deleted</td><td>all packages are updated</td></tr>
     * </table>
     *
     * @param packageName The package that is updated, or {@code null} if all packages should be
     *                    updated
     * @param pkg The package that is updated, or {@code null} if all packages should be updated or
     *            package is deleted
     *
     * @return {@code true} if a permission source package might have changed
     */
    private boolean updatePermissionSourcePackage(@Nullable String packageName,
            @Nullable PackageParser.Package pkg) {
        boolean changed = false;

        Set<BasePermission> needsUpdate = null;
        Set<BasePermission> needsUpdate = null;
        synchronized (mLock) {
        synchronized (mLock) {
            final Iterator<BasePermission> it = mSettings.mPermissions.values().iterator();
            final Iterator<BasePermission> it = mSettings.mPermissions.values().iterator();
@@ -2546,9 +2653,9 @@ public class PermissionManagerService {
                if (bp.getSourcePackageSetting() != null) {
                if (bp.getSourcePackageSetting() != null) {
                    if (packageName != null && packageName.equals(bp.getSourcePackageName())
                    if (packageName != null && packageName.equals(bp.getSourcePackageName())
                        && (pkg == null || !hasPermission(pkg, bp.getName()))) {
                        && (pkg == null || !hasPermission(pkg, bp.getName()))) {
                        Slog.i(TAG, "Removing old permission tree: " + bp.getName()
                        Slog.i(TAG, "Removing permission " + bp.getName()
                                + " from package " + bp.getSourcePackageName());
                                + " that used to be declared by " + bp.getSourcePackageName());
                        flags |= UPDATE_PERMISSIONS_ALL;
                        changed = true;
                        it.remove();
                        it.remove();
                    }
                    }
                    continue;
                    continue;
@@ -2577,11 +2684,30 @@ public class PermissionManagerService {
                }
                }
            }
            }
        }
        }
        return flags;
        return changed;
    }
    }


    private int updatePermissionTrees(String packageName, PackageParser.Package pkg,
    /**
            int flags) {
     * Update which app owns a permission trees.
     *
     * <p>Possible parameter combinations
     * <table>
     *     <tr><th></th><th>packageName != null</th><th>packageName == null</th></tr>
     *     <tr><th>pkg != null</th><td>package is updated</td><td>invalid</td></tr>
     *     <tr><th>pkg == null</th><td>package is deleted</td><td>all packages are updated</td></tr>
     * </table>
     *
     * @param packageName The package that is updated, or {@code null} if all packages should be
     *                    updated
     * @param pkg The package that is updated, or {@code null} if all packages should be updated or
     *            package is deleted
     *
     * @return {@code true} if a permission tree ownership might have changed
     */
    private boolean updatePermissionTreeSourcePackage(@Nullable String packageName,
            @Nullable PackageParser.Package pkg) {
        boolean changed = false;

        Set<BasePermission> needsUpdate = null;
        Set<BasePermission> needsUpdate = null;
        synchronized (mLock) {
        synchronized (mLock) {
            final Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
            final Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
@@ -2590,9 +2716,9 @@ public class PermissionManagerService {
                if (bp.getSourcePackageSetting() != null) {
                if (bp.getSourcePackageSetting() != null) {
                    if (packageName != null && packageName.equals(bp.getSourcePackageName())
                    if (packageName != null && packageName.equals(bp.getSourcePackageName())
                        && (pkg == null || !hasPermission(pkg, bp.getName()))) {
                        && (pkg == null || !hasPermission(pkg, bp.getName()))) {
                        Slog.i(TAG, "Removing old permission tree: " + bp.getName()
                        Slog.i(TAG, "Removing permission tree " + bp.getName()
                                + " from package " + bp.getSourcePackageName());
                                + " that used to be declared by " + bp.getSourcePackageName());
                        flags |= UPDATE_PERMISSIONS_ALL;
                        changed = true;
                        it.remove();
                        it.remove();
                    }
                    }
                    continue;
                    continue;
@@ -2621,7 +2747,7 @@ public class PermissionManagerService {
                }
                }
            }
            }
        }
        }
        return flags;
        return changed;
    }
    }


    private void updatePermissionFlags(String permName, String packageName, int flagMask,
    private void updatePermissionFlags(String permName, String packageName, int flagMask,
@@ -2947,14 +3073,16 @@ public class PermissionManagerService {
                    overridePolicy, userId, callback);
                    overridePolicy, userId, callback);
        }
        }
        @Override
        @Override
        public void updatePermissions(String packageName, Package pkg, boolean replaceGrant,
        public void updatePermissions(@NonNull String packageName, @Nullable Package pkg,
                Collection<PackageParser.Package> allPackages, PermissionCallback callback) {
                @NonNull Collection<PackageParser.Package> allPackages,
                @NonNull PermissionCallback callback) {
            PermissionManagerService.this.updatePermissions(
            PermissionManagerService.this.updatePermissions(
                    packageName, pkg, replaceGrant, allPackages, callback);
                    packageName, pkg, allPackages, callback);
        }
        }
        @Override
        @Override
        public void updateAllPermissions(String volumeUuid, boolean sdkUpdated,
        public void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdated,
                Collection<PackageParser.Package> allPackages, PermissionCallback callback) {
                @NonNull Collection<PackageParser.Package> allPackages,
                @NonNull PermissionCallback callback) {
            PermissionManagerService.this.updateAllPermissions(
            PermissionManagerService.this.updateAllPermissions(
                    volumeUuid, sdkUpdated, allPackages, callback);
                    volumeUuid, sdkUpdated, allPackages, callback);
        }
        }
+32 −4
Original line number Original line Diff line number Diff line
@@ -89,11 +89,39 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
            @NonNull String packageName, boolean overridePolicy, int userId,
            @NonNull String packageName, boolean overridePolicy, int userId,
            @Nullable PermissionCallback callback);
            @Nullable PermissionCallback callback);


    public abstract void updatePermissions(@Nullable String packageName,
    /**
            @Nullable PackageParser.Package pkg, boolean replaceGrant,
     * Update permissions when a package changed.
            @NonNull Collection<PackageParser.Package> allPacakges, PermissionCallback callback);
     *
     * <p><ol>
     *     <li>Reconsider the ownership of permission</li>
     *     <li>Update the state (grant, flags) of the permissions</li>
     * </ol>
     *
     * @param packageName The package that is updated
     * @param pkg The package that is updated, or {@code null} if package is deleted
     * @param allPackages All currently known packages
     * @param callback Callback to call after permission changes
     */
    public abstract void updatePermissions(@NonNull String packageName,
            @Nullable PackageParser.Package pkg,
            @NonNull Collection<PackageParser.Package> allPackages,
            @NonNull PermissionCallback callback);

    /**
     * Update all permissions for all apps.
     *
     * <p><ol>
     *     <li>Reconsider the ownership of permission</li>
     *     <li>Update the state (grant, flags) of the permissions</li>
     * </ol>
     *
     * @param volumeUuid The volume of the packages to be updated, {@code null} for all volumes
     * @param allPackages All currently known packages
     * @param callback Callback to call after permission changes
     */
    public abstract void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdate,
    public abstract void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdate,
            @NonNull Collection<PackageParser.Package> allPacakges, PermissionCallback callback);
            @NonNull Collection<PackageParser.Package> allPackages,
            @NonNull PermissionCallback callback);


    /**
    /**
     * We might auto-grant permissions if any permission of the group is already granted. Hence if
     * We might auto-grant permissions if any permission of the group is already granted. Hence if