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

Commit b20cf04b authored by Philip P. Moltmann's avatar Philip P. Moltmann Committed by Android (Google) Code Review
Browse files

Merge "Refactor updatePermissions path"

parents cc66ee1e dc65aa3f
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