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

Commit f331c8f5 authored by Thomas Vannet's avatar Thomas Vannet
Browse files

Immediately revoke permission on process kill after a self-revocation

Test: atest android.permission.cts.RevokeOwnPermissionTest
Bug: 210387494
Change-Id: Iaa3a4c00847d5411c5b829d190eba8231d046d8c
parent 395f8dee
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -835,17 +835,17 @@ public final class PermissionControllerManager {
     *
     * @param packageName The name of the package for which the permissions will be revoked.
     * @param permissions List of permissions to be revoked.
     * @param callback Callback called when the revocation request has been completed.
     *
     * @see Context#revokeOwnPermissionsOnKill(Collection)
     *
     * @hide
     */
    public void revokeOwnPermissionsOnKill(@NonNull String packageName,
            @NonNull List<String> permissions) {
            @NonNull List<String> permissions, AndroidFuture<Void> callback) {
        mRemoteService.postAsync(service -> {
            AndroidFuture<Void> future = new AndroidFuture<>();
            service.revokeOwnPermissionsOnKill(packageName, permissions, future);
            return future;
            service.revokeOwnPermissionsOnKill(packageName, permissions, callback);
            return callback;
        }).whenComplete((result, err) -> {
            if (err != null) {
                Log.e(TAG, "Failed to self revoke " + String.join(",", permissions)
+26 −2
Original line number Diff line number Diff line
@@ -162,7 +162,10 @@ public class OneTimePermissionUserManager {
     * The delay to wait before revoking on the event an app is terminated. Recommended to be long
     * enough so that apps don't lose permission on an immediate restart
     */
    private static long getKilledDelayMillis() {
    private long getKilledDelayMillis(boolean isSelfRevokedPermissionSession) {
        if (isSelfRevokedPermissionSession) {
            return 0;
        }
        return DeviceConfig.getLong(DeviceConfig.NAMESPACE_PERMISSIONS,
                PROPERTY_KILLED_DELAY_CONFIG_KEY, DEFAULT_KILLED_DELAY_MILLIS);
    }
@@ -175,6 +178,18 @@ public class OneTimePermissionUserManager {
        mContext.registerReceiver(mUninstallListener, new IntentFilter(Intent.ACTION_UID_REMOVED));
    }

    void setSelfRevokedPermissionSession(int uid) {
        synchronized (mLock) {
            PackageInactivityListener listener = mListeners.get(uid);
            if (listener == null) {
                Log.e(LOG_TAG, "Could not set session for uid " + uid
                        + " as self-revoke session: session not found");
                return;
            }
            listener.setSelfRevokedPermissionSession();
        }
    }

    /**
     * A class which watches a package for inactivity and notifies the permission controller when
     * the package becomes inactive
@@ -189,6 +204,7 @@ public class OneTimePermissionUserManager {
        private final int mImportanceToResetTimer;
        private final int mImportanceToKeepSessionAlive;

        private boolean mIsSelfRevokedPermissionSession;
        private boolean mIsAlarmSet;
        private boolean mIsFinished;

@@ -255,7 +271,7 @@ public class OneTimePermissionUserManager {
                            }
                            onImportanceChanged(mUid, imp);
                        }
                    }, mToken, getKilledDelayMillis());
                    }, mToken, getKilledDelayMillis(mIsSelfRevokedPermissionSession));
                    return;
                }
                if (importance > mImportanceToResetTimer) {
@@ -290,6 +306,14 @@ public class OneTimePermissionUserManager {
            }
        }

        /**
         * Marks the session as a self-revoke session, which does not delay the revocation when
         * the app is restarting.
         */
        public void setSelfRevokedPermissionSession() {
            mIsSelfRevokedPermissionSession = true;
        }

        /**
         * Set the alarm which will callback when the package is inactive
         */
+11 −1
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.Preconditions;
import com.android.internal.util.function.TriFunction;
import com.android.server.LocalServices;
@@ -560,7 +561,16 @@ public class PermissionManagerService extends IPermissionManager.Stub {
    @Override
    public void revokeOwnPermissionsOnKill(@NonNull String packageName,
            @NonNull List<String> permissions) {
        mPermissionManagerServiceImpl.revokeOwnPermissionsOnKill(packageName, permissions);
        final int callingUid = Binder.getCallingUid();
        final int callingUserId = UserHandle.getUserId(callingUid);
        AndroidFuture<Void> future = new AndroidFuture<>();
        future.whenComplete((result, err) -> {
            if (err == null) {
                getOneTimePermissionUserManager(callingUserId)
                        .setSelfRevokedPermissionSession(callingUid);
            }
        });
        mPermissionManagerServiceImpl.revokeOwnPermissionsOnKill(packageName, permissions, future);
    }

    @Override
+5 −2
Original line number Diff line number Diff line
@@ -113,6 +113,7 @@ import android.util.SparseBooleanArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.compat.IPlatformCompat;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.os.RoSystemProperties;
@@ -1592,7 +1593,8 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
    }

    @Override
    public void revokeOwnPermissionsOnKill(String packageName, List<String> permissions) {
    public void revokeOwnPermissionsOnKill(String packageName, List<String> permissions,
            AndroidFuture<Void> callback) {
        final int callingUid = Binder.getCallingUid();
        int callingUserId = UserHandle.getUserId(callingUid);
        int targetPackageUid = mPackageManagerInt.getPackageUid(packageName, 0, callingUserId);
@@ -1607,7 +1609,8 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
                        + permName + " because it does not hold that permission");
            }
        }
        mPermissionControllerManager.revokeOwnPermissionsOnKill(packageName, permissions);
        mPermissionControllerManager.revokeOwnPermissionsOnKill(packageName, permissions,
                callback);
    }

    private boolean mayManageRolePermission(int uid) {
+4 −1
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.content.pm.permission.SplitPermissionInfoParcelable;
import android.permission.IOnPermissionsChangeListener;
import android.permission.PermissionManagerInternal;

import com.android.internal.infra.AndroidFuture;
import com.android.server.pm.parsing.pkg.AndroidPackage;

import java.io.FileDescriptor;
@@ -343,8 +344,10 @@ public interface PermissionManagerServiceInterface extends PermissionManagerInte
     *
     * @param packageName The name of the package for which the permissions will be revoked.
     * @param permissions List of permissions to be revoked.
     * @param callback Callback called when the revocation request has been completed.
     */
    void revokeOwnPermissionsOnKill(String packageName, List<String> permissions);
    void revokeOwnPermissionsOnKill(String packageName, List<String> permissions,
            AndroidFuture<Void> callback);

    /**
     * Get whether you should show UI with rationale for requesting a permission. You should do this