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

Commit 904b0d59 authored by Hai Zhang's avatar Hai Zhang
Browse files

Allow resetting runtime permissions for all packages with a single write.

Bug: 232134765
Test: presubmit
Change-Id: I81d135a6606957ac2e079127a7eb825b00ed2417
parent e020d397
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -331,6 +331,16 @@ public class ArrayUtils {
        return array;
    }

    @NonNull
    public static int[] convertToIntArray(@NonNull ArraySet<Integer> set) {
        final int size = set.size();
        int[] array = new int[size];
        for (int i = 0; i < size; i++) {
            array[i] = set.valueAt(i);
        }
        return array;
    }

    public static @Nullable long[] convertToLongArray(@Nullable int[] intArray) {
        if (intArray == null) return null;
        long[] array = new long[intArray.length];
+1 −6
Original line number Diff line number Diff line
@@ -48,7 +48,6 @@ import android.util.Xml;

import com.android.internal.util.ArrayUtils;
import com.android.server.net.NetworkPolicyManagerInternal;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;

import org.xmlpull.v1.XmlPullParser;
@@ -595,11 +594,7 @@ final class PreferredActivityHelper {
            synchronized (mPm.mLock) {
                mPm.mSettings.applyDefaultPreferredAppsLPw(userId);
                mPm.mDomainVerificationManager.clearUser(userId);
                final int numPackages = mPm.mPackages.size();
                for (int i = 0; i < numPackages; i++) {
                    final AndroidPackage pkg = mPm.mPackages.valueAt(i);
                    mPm.mPermissionManager.resetRuntimePermissions(pkg, userId);
                }
                mPm.mPermissionManager.resetRuntimePermissionsForUser(userId);
            }
            updateDefaultHomeNotLocked(mPm.snapshotComputer(), userId);
            resetNetworkPolicies(userId);
+4 −0
Original line number Diff line number Diff line
@@ -780,6 +780,10 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        public void resetRuntimePermissions(@NonNull AndroidPackage pkg, @UserIdInt int userId) {
            mPermissionManagerServiceImpl.resetRuntimePermissions(pkg, userId);
        }
        @Override
        public void resetRuntimePermissionsForUser(@UserIdInt int userId) {
            mPermissionManagerServiceImpl.resetRuntimePermissionsForUser(userId);
        }

        @Override
        public Permission getPermissionTEMP(String permName) {
+59 −43
Original line number Diff line number Diff line
@@ -103,7 +103,6 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.EventLog;
import android.util.IntArray;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
@@ -1661,30 +1660,16 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
    /**
     * Reverts user permission state changes (permissions and flags).
     *
     * @param pkg The package for which to reset.
     * @param filterPkg The package for which to reset, or {@code null} for all packages.
     * @param userId The device user for which to do a reset.
     */
    private void resetRuntimePermissionsInternal(@NonNull AndroidPackage pkg,
    private void resetRuntimePermissionsInternal(@Nullable AndroidPackage filterPkg,
            @UserIdInt int userId) {
        final String packageName = pkg.getPackageName();

        // These are flags that can change base on user actions.
        final int userSettableMask = FLAG_PERMISSION_USER_SET
                | FLAG_PERMISSION_USER_FIXED
                | FLAG_PERMISSION_REVOKED_COMPAT
                | FLAG_PERMISSION_REVIEW_REQUIRED
                | FLAG_PERMISSION_ONE_TIME
                | FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY;

        final int policyOrSystemFlags = FLAG_PERMISSION_SYSTEM_FIXED
                | FLAG_PERMISSION_POLICY_FIXED;

        // Delay and combine non-async permission callbacks
        final int permissionCount = ArrayUtils.size(pkg.getRequestedPermissions());
        final boolean[] permissionRemoved = new boolean[1];
        final ArraySet<Long> revokedPermissions = new ArraySet<>();
        final IntArray syncUpdatedUsers = new IntArray(permissionCount);
        final IntArray asyncUpdatedUsers = new IntArray(permissionCount);
        final ArraySet<Integer> syncUpdatedUsers = new ArraySet<>();
        final ArraySet<Integer> asyncUpdatedUsers = new ArraySet<>();

        PermissionCallback delayingPermCallback = new PermissionCallback() {
            public void onGidsChanged(int appId, int userId) {
@@ -1746,6 +1731,55 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
            }
        };

        if (filterPkg != null) {
            resetRuntimePermissionsInternal(filterPkg, userId, delayingPermCallback);
        } else {
            mPackageManagerInt.forEachPackage(pkg ->
                    resetRuntimePermissionsInternal(pkg, userId, delayingPermCallback));
        }

        // Execute delayed callbacks
        if (permissionRemoved[0]) {
            mDefaultPermissionCallback.onPermissionRemoved();
        }

        // Slight variation on the code in mPermissionCallback.onPermissionRevoked() as we cannot
        // kill uid while holding mPackages-lock
        if (!revokedPermissions.isEmpty()) {
            int numRevokedPermissions = revokedPermissions.size();
            for (int i = 0; i < numRevokedPermissions; i++) {
                int revocationUID = IntPair.first(revokedPermissions.valueAt(i));
                int revocationUserId = IntPair.second(revokedPermissions.valueAt(i));

                mOnPermissionChangeListeners.onPermissionsChanged(revocationUID);

                // Kill app later as we are holding mPackages
                mHandler.post(() -> killUid(UserHandle.getAppId(revocationUID), revocationUserId,
                        KILL_APP_REASON_PERMISSIONS_REVOKED));
            }
        }

        mPackageManagerInt.writePermissionSettings(ArrayUtils.convertToIntArray(syncUpdatedUsers),
                false);
        mPackageManagerInt.writePermissionSettings(ArrayUtils.convertToIntArray(asyncUpdatedUsers),
                true);
    }

    private void resetRuntimePermissionsInternal(@NonNull AndroidPackage pkg,
            @UserIdInt int userId, @NonNull PermissionCallback delayingPermCallback) {
        // These are flags that can change base on user actions.
        final int userSettableMask = FLAG_PERMISSION_USER_SET
                | FLAG_PERMISSION_USER_FIXED
                | FLAG_PERMISSION_REVOKED_COMPAT
                | FLAG_PERMISSION_REVIEW_REQUIRED
                | FLAG_PERMISSION_ONE_TIME
                | FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY;

        final int policyOrSystemFlags = FLAG_PERMISSION_SYSTEM_FIXED
                | FLAG_PERMISSION_POLICY_FIXED;

        final String packageName = pkg.getPackageName();
        final int permissionCount = ArrayUtils.size(pkg.getRequestedPermissions());
        for (int i = 0; i < permissionCount; i++) {
            final String permName = pkg.getRequestedPermissions().get(i);

@@ -1824,30 +1858,6 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
                        userId, null, delayingPermCallback);
            }
        }

        // Execute delayed callbacks
        if (permissionRemoved[0]) {
            mDefaultPermissionCallback.onPermissionRemoved();
        }

        // Slight variation on the code in mPermissionCallback.onPermissionRevoked() as we cannot
        // kill uid while holding mPackages-lock
        if (!revokedPermissions.isEmpty()) {
            int numRevokedPermissions = revokedPermissions.size();
            for (int i = 0; i < numRevokedPermissions; i++) {
                int revocationUID = IntPair.first(revokedPermissions.valueAt(i));
                int revocationUserId = IntPair.second(revokedPermissions.valueAt(i));

                mOnPermissionChangeListeners.onPermissionsChanged(revocationUID);

                // Kill app later as we are holding mPackages
                mHandler.post(() -> killUid(UserHandle.getAppId(revocationUID), revocationUserId,
                        KILL_APP_REASON_PERMISSIONS_REVOKED));
            }
        }

        mPackageManagerInt.writePermissionSettings(syncUpdatedUsers.toArray(), false);
        mPackageManagerInt.writePermissionSettings(asyncUpdatedUsers.toArray(), true);
    }

    /**
@@ -5177,6 +5187,12 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
        resetRuntimePermissionsInternal(pkg, userId);
    }

    @Override
    public void resetRuntimePermissionsForUser(@UserIdInt int userId) {
        Preconditions.checkArgumentNonNegative(userId, "userId");
        resetRuntimePermissionsInternal(null, userId);
    }

    @Override
    public Permission getPermissionTEMP(String permName) {
        synchronized (mLock) {
+7 −0
Original line number Diff line number Diff line
@@ -427,6 +427,13 @@ public interface PermissionManagerServiceInterface extends PermissionManagerInte
    void resetRuntimePermissions(@NonNull AndroidPackage pkg,
            @UserIdInt int userId);

    /**
     * Reset the runtime permission state changes for all packages in a user.
     *
     * @param userId the user ID
     */
    void resetRuntimePermissionsForUser(@UserIdInt int userId);

    /**
     * Read legacy permission state from package settings.
     *
Loading