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

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

Use pooledLambda in RuntimePermissionPresenterService

And check parameters at trust boundaries

Test: Looked at AppInfo in Settings (uses RuntimePermissionPresenterService)
Change-Id: Ie70f64c1bc5435e1d284c37cc6fec208468b3a0a
parent f3867a70
Loading
Loading
Loading
Loading
+78 −96
Original line number Diff line number Diff line
@@ -16,13 +16,15 @@

package android.content.pm.permission;

import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
@@ -32,7 +34,7 @@ import android.permissionpresenterservice.RuntimePermissionPresenterService;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.function.pooled.PooledLambda;

import java.util.ArrayList;
import java.util.Collections;
@@ -109,13 +111,11 @@ public final class RuntimePermissionPresenter {
     */
    public void getAppPermissions(@NonNull String packageName,
            @NonNull OnResultCallback callback, @Nullable Handler handler) {
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = packageName;
        args.arg2 = callback;
        args.arg3 = handler;
        Message message = mRemoteService.obtainMessage(
                RemoteService.MSG_GET_APP_PERMISSIONS, args);
        mRemoteService.processMessage(message);
        checkNotNull(packageName);
        checkNotNull(callback);

        mRemoteService.processMessage(obtainMessage(RemoteService::getAppPermissions,
                mRemoteService, packageName, callback, handler));
    }

    /**
@@ -124,24 +124,20 @@ public final class RuntimePermissionPresenter {
     * @param packageName The package for which to revoke
     * @param permissionName The permission to revoke
     */
    public void revokeRuntimePermission(String packageName, String permissionName) {
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = packageName;
        args.arg2 = permissionName;
    public void revokeRuntimePermission(@NonNull String packageName,
            @NonNull String permissionName) {
        checkNotNull(packageName);
        checkNotNull(permissionName);

        Message message = mRemoteService.obtainMessage(
                RemoteService.MSG_REVOKE_APP_PERMISSIONS, args);
        mRemoteService.processMessage(message);
        mRemoteService.processMessage(obtainMessage(RemoteService::revokeAppPermissions,
                mRemoteService, packageName, permissionName));
    }

    private static final class RemoteService
            extends Handler implements ServiceConnection {
        private static final long UNBIND_TIMEOUT_MILLIS = 10000;

        public static final int MSG_GET_APP_PERMISSIONS = 1;
        public static final int MSG_GET_APPS_USING_PERMISSIONS = 2;
        public static final int MSG_UNBIND = 3;
        public static final int MSG_REVOKE_APP_PERMISSIONS = 4;
        public static final int MSG_UNBIND = 0;

        private final Object mLock = new Object();

@@ -191,15 +187,8 @@ public final class RuntimePermissionPresenter {
            }
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_GET_APP_PERMISSIONS: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    final String packageName = (String) args.arg1;
                    final OnResultCallback callback = (OnResultCallback) args.arg2;
                    final Handler handler = (Handler) args.arg3;
                    args.recycle();
        private void getAppPermissions(@NonNull String packageName,
                @NonNull OnResultCallback callback, @Nullable Handler handler) {
            final IRuntimePermissionPresenter remoteInstance;
            synchronized (mLock) {
                remoteInstance = mRemoteInstance;
@@ -209,9 +198,7 @@ public final class RuntimePermissionPresenter {
            }
            try {
                remoteInstance.getAppPermissions(packageName,
                                new RemoteCallback(new RemoteCallback.OnResultListener() {
                            @Override
                            public void onResult(Bundle result) {
                        new RemoteCallback(result -> {
                            final List<RuntimePermissionPresentationInfo> reportedPermissions;
                            List<RuntimePermissionPresentationInfo> permissions = null;
                            if (result != null) {
@@ -222,38 +209,24 @@ public final class RuntimePermissionPresenter {
                            }
                            reportedPermissions = permissions;
                            if (handler != null) {
                                    handler.post(new Runnable() {
                                        @Override
                                        public void run() {
                                            callback.onGetAppPermissions(reportedPermissions);
                                        }
                                    });
                                handler.post(
                                        () -> callback.onGetAppPermissions(reportedPermissions));
                            } else {
                                callback.onGetAppPermissions(reportedPermissions);
                            }
                            }
                        }, this));
            } catch (RemoteException re) {
                Log.e(TAG, "Error getting app permissions", re);
            }
            scheduleUnbind();
                } break;

                case MSG_UNBIND: {
            synchronized (mLock) {
                        if (mBound) {
                            mContext.unbindService(this);
                            mBound = false;
                scheduleNextMessageIfNeededLocked();
            }
                        mRemoteInstance = null;
        }
                } break;

                case MSG_REVOKE_APP_PERMISSIONS: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    final String packageName = (String) args.arg1;
                    final String permissionName = (String) args.arg2;
                    args.recycle();
        private void revokeAppPermissions(@NonNull String packageName,
                @NonNull String permissionName) {
            final IRuntimePermissionPresenter remoteInstance;
            synchronized (mLock) {
                remoteInstance = mRemoteInstance;
@@ -266,14 +239,22 @@ public final class RuntimePermissionPresenter {
            } catch (RemoteException re) {
                Log.e(TAG, "Error getting app permissions", re);
            }
                } break;
            }

            synchronized (mLock) {
                scheduleNextMessageIfNeededLocked();
            }
        }

        private void unbind() {
            synchronized (mLock) {
                if (mBound) {
                    mContext.unbindService(this);
                    mBound = false;
                }
                mRemoteInstance = null;
            }
        }

        @GuardedBy("mLock")
        private void scheduleNextMessageIfNeededLocked() {
            if (mBound && mRemoteInstance != null && !mPendingWork.isEmpty()) {
@@ -284,7 +265,8 @@ public final class RuntimePermissionPresenter {

        private void scheduleUnbind() {
            removeMessages(MSG_UNBIND);
            sendEmptyMessageDelayed(MSG_UNBIND, UNBIND_TIMEOUT_MILLIS);
            sendMessageDelayed(PooledLambda.obtainMessage(RemoteService::unbind, this)
                    .setWhat(MSG_UNBIND), UNBIND_TIMEOUT_MILLIS);
        }
    }
}
+27 −53
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package android.permissionpresenterservice;

import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;

import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.app.Service;
@@ -27,12 +30,8 @@ import android.content.pm.permission.RuntimePermissionPresenter;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteCallback;

import com.android.internal.os.SomeArgs;

import java.util.List;

/**
@@ -63,7 +62,7 @@ public abstract class RuntimePermissionPresenterService extends Service {
    @Override
    public final void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        mHandler = new MyHandler(base.getMainLooper());
        mHandler = new Handler(base.getMainLooper());
    }

    /**
@@ -71,7 +70,8 @@ public abstract class RuntimePermissionPresenterService extends Service {
     *
     * @param packageName The package for which to query.
     */
    public abstract List<RuntimePermissionPresentationInfo> onGetAppPermissions(String packageName);
    public abstract List<RuntimePermissionPresentationInfo> onGetAppPermissions(
            @NonNull String packageName);

    /**
     * Revokes the permission {@code permissionName} for app {@code packageName}
@@ -87,61 +87,35 @@ public abstract class RuntimePermissionPresenterService extends Service {
        return new IRuntimePermissionPresenter.Stub() {
            @Override
            public void getAppPermissions(String packageName, RemoteCallback callback) {
                SomeArgs args = SomeArgs.obtain();
                args.arg1 = packageName;
                args.arg2 = callback;
                mHandler.obtainMessage(MyHandler.MSG_GET_APP_PERMISSIONS,
                        args).sendToTarget();
                checkNotNull(packageName, "packageName");
                checkNotNull(callback, "callback");

                mHandler.sendMessage(
                        obtainMessage(RuntimePermissionPresenterService::getAppPermissions,
                                RuntimePermissionPresenterService.this, packageName, callback));
            }

            @Override
            public void revokeRuntimePermission(String packageName, String permissionName) {
                SomeArgs args = SomeArgs.obtain();
                args.arg1 = packageName;
                args.arg2 = permissionName;
                mHandler.obtainMessage(MyHandler.MSG_REVOKE_APP_PERMISSION,
                        args).sendToTarget();
                checkNotNull(packageName, "packageName");
                checkNotNull(permissionName, "permissionName");

                mHandler.sendMessage(
                        obtainMessage(RuntimePermissionPresenterService::onRevokeRuntimePermission,
                                RuntimePermissionPresenterService.this, packageName,
                                permissionName));
            }
        };
    }

    private final class MyHandler extends Handler {
        public static final int MSG_GET_APP_PERMISSIONS = 1;
        public static final int MSG_GET_APPS_USING_PERMISSIONS = 2;
        public static final int MSG_REVOKE_APP_PERMISSION = 3;

        public MyHandler(Looper looper) {
            super(looper, null, false);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_GET_APP_PERMISSIONS: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    String packageName = (String) args.arg1;
                    RemoteCallback callback = (RemoteCallback) args.arg2;
                    args.recycle();
                    List<RuntimePermissionPresentationInfo> permissions =
                            onGetAppPermissions(packageName);
    private void getAppPermissions(@NonNull String packageName, @NonNull RemoteCallback callback) {
        List<RuntimePermissionPresentationInfo> permissions = onGetAppPermissions(packageName);
        if (permissions != null && !permissions.isEmpty()) {
            Bundle result = new Bundle();
                        result.putParcelableList(RuntimePermissionPresenter.KEY_RESULT,
                                permissions);
            result.putParcelableList(RuntimePermissionPresenter.KEY_RESULT, permissions);
            callback.sendResult(result);
        } else {
            callback.sendResult(null);
        }
                } break;
                case MSG_REVOKE_APP_PERMISSION: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    String packageName = (String) args.arg1;
                    String permissionName = (String) args.arg2;
                    args.recycle();

                    onRevokeRuntimePermission(packageName, permissionName);
                } break;
            }
        }
    }
}