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

Commit a4959e56 authored by Hai Zhang's avatar Hai Zhang
Browse files

Add RoleControllerManager for role controller service.

This allows us to expose both system-only and app available APIs for
role in RoleControllerService.

Bug: 127691087
Test: manual
Change-Id: I86fe3736fc28516aae25d48efe3ba599ffdf45d5
parent 88da4473
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@ java_defaults {
        "core/java/android/app/prediction/IPredictionCallback.aidl",
        "core/java/android/app/prediction/IPredictionManager.aidl",
        "core/java/android/app/role/IOnRoleHoldersChangedListener.aidl",
        "core/java/android/app/role/IRoleController.aidl",
        "core/java/android/app/role/IRoleManager.aidl",
        "core/java/android/app/role/IRoleManagerCallback.aidl",
        "core/java/android/app/slice/ISliceManager.aidl",
@@ -274,7 +275,6 @@ java_defaults {
        "core/java/android/os/storage/IStorageShutdownObserver.aidl",
        "core/java/android/os/storage/IObbActionListener.aidl",
        "core/java/android/permission/IPermissionController.aidl",
        "core/java/android/rolecontrollerservice/IRoleControllerService.aidl",
        ":keystore_aidl",
        "core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl",
        "core/java/android/service/appprediction/IPredictionService.aidl",
+11 −15
Original line number Diff line number Diff line
@@ -1116,6 +1116,17 @@ package android.app.role {
    method public void onRoleHoldersChanged(@NonNull String, @NonNull android.os.UserHandle);
  }
  public abstract class RoleControllerService extends android.app.Service {
    ctor public RoleControllerService();
    method public abstract void onAddRoleHolder(@NonNull String, @NonNull String, int, @NonNull android.app.role.RoleManagerCallback);
    method @Nullable public final android.os.IBinder onBind(@Nullable android.content.Intent);
    method public abstract void onClearRoleHolders(@NonNull String, int, @NonNull android.app.role.RoleManagerCallback);
    method public abstract void onGrantDefaultRoles(@NonNull android.app.role.RoleManagerCallback);
    method public abstract void onRemoveRoleHolder(@NonNull String, @NonNull String, int, @NonNull android.app.role.RoleManagerCallback);
    method public abstract void onSmsKillSwitchToggled(boolean);
    field public static final String SERVICE_INTERFACE = "android.app.role.RoleControllerService";
  }
  public final class RoleManager {
    method @RequiresPermission(android.Manifest.permission.OBSERVE_ROLE_HOLDERS) public void addOnRoleHoldersChangedListenerAsUser(@NonNull java.util.concurrent.Executor, @NonNull android.app.role.OnRoleHoldersChangedListener, @NonNull android.os.UserHandle);
    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void addRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.role.RoleManagerCallback);
@@ -6166,21 +6177,6 @@ package android.provider {
}
package android.rolecontrollerservice {
  public abstract class RoleControllerService extends android.app.Service {
    ctor public RoleControllerService();
    method public abstract void onAddRoleHolder(@NonNull String, @NonNull String, int, @NonNull android.app.role.RoleManagerCallback);
    method @Nullable public final android.os.IBinder onBind(@Nullable android.content.Intent);
    method public abstract void onClearRoleHolders(@NonNull String, int, @NonNull android.app.role.RoleManagerCallback);
    method public abstract void onGrantDefaultRoles(@NonNull android.app.role.RoleManagerCallback);
    method public abstract void onRemoveRoleHolder(@NonNull String, @NonNull String, int, @NonNull android.app.role.RoleManagerCallback);
    method public abstract void onSmsKillSwitchToggled(boolean);
    field public static final String SERVICE_INTERFACE = "android.rolecontrollerservice.RoleControllerService";
  }
}
package android.security.keystore {
  public abstract class AttestationUtils {
+9 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.app.contentsuggestions.IContentSuggestionsManager;
import android.app.job.IJobScheduler;
import android.app.job.JobScheduler;
import android.app.prediction.AppPredictionManager;
import android.app.role.RoleControllerManager;
import android.app.role.RoleManager;
import android.app.slice.SliceManager;
import android.app.timedetector.TimeDetector;
@@ -1243,6 +1244,14 @@ final class SystemServiceRegistry {
                        return new RoleManager(ctx.getOuterContext());
                    }});

        registerService(Context.ROLE_CONTROLLER_SERVICE, RoleControllerManager.class,
                new CachedServiceFetcher<RoleControllerManager>() {
                    @Override
                    public RoleControllerManager createService(ContextImpl ctx)
                            throws ServiceNotFoundException {
                        return new RoleControllerManager(ctx.getOuterContext());
                    }});

        registerService(Context.ROLLBACK_SERVICE, RollbackManager.class,
                new CachedServiceFetcher<RollbackManager>() {
                    @Override
+5 −5
Original line number Diff line number Diff line
@@ -14,14 +14,16 @@
 * limitations under the License.
 */

package android.rolecontrollerservice;
package android.app.role;

import android.app.role.IRoleManagerCallback;

/**
 * @hide
 */
oneway interface IRoleControllerService {
oneway interface IRoleController {

    void onGrantDefaultRoles(in IRoleManagerCallback callback);

    void onAddRoleHolder(in String roleName, in String packageName, int flags,
                         in IRoleManagerCallback callback);
@@ -31,7 +33,5 @@ oneway interface IRoleControllerService {

    void onClearRoleHolders(in String roleName, int flags, in IRoleManagerCallback callback);

    void onGrantDefaultRoles(in IRoleManagerCallback callback);

    void onSmsKillSwitchToggled(boolean smsRestrictionEnabled);
    void onSmsKillSwitchToggled(boolean enabled);
}
+474 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.app.role;

import android.annotation.NonNull;
import android.annotation.SystemService;
import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
import com.android.internal.infra.AbstractRemoteService;

/**
 * Interface for communicating with the role controller.
 *
 * @hide
 */
@SystemService(Context.ROLE_CONTROLLER_SERVICE)
public class RoleControllerManager {

    private static final String LOG_TAG = RoleControllerManager.class.getSimpleName();

    private static final Object sRemoteServicesLock = new Object();
    /**
     * Global remote services (per user) used by all {@link RoleControllerManager managers}.
     */
    @GuardedBy("sRemoteServicesLock")
    private static final SparseArray<RemoteService> sRemoteServices = new SparseArray<>();

    @NonNull
    private final RemoteService mRemoteService;

    public RoleControllerManager(@NonNull Context context, @NonNull Handler handler) {
        synchronized (sRemoteServicesLock) {
            int userId = context.getUserId();
            RemoteService remoteService = sRemoteServices.get(userId);
            if (remoteService == null) {
                Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE);
                PackageManager packageManager = context.getPackageManager();
                intent.setPackage(packageManager.getPermissionControllerPackageName());
                ResolveInfo resolveInfo = packageManager.resolveService(intent, 0);

                remoteService = new RemoteService(context.getApplicationContext(),
                        resolveInfo.getComponentInfo().getComponentName(), handler, userId);
                sRemoteServices.put(userId, remoteService);
            }
            mRemoteService = remoteService;
        }
    }

    public RoleControllerManager(@NonNull Context context) {
        this(context, context.getMainThreadHandler());
    }

    /**
     * @see RoleControllerService#onGrantDefaultRoles(RoleManagerCallback)
     */
    public void onGrantDefaultRoles(@NonNull IRoleManagerCallback callback) {
        mRemoteService.scheduleRequest(new OnGrantDefaultRolesRequest(mRemoteService, callback));
    }

    /**
     * @see RoleControllerService#onAddRoleHolder(String, String, int, RoleManagerCallback)
     */
    public void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
            @RoleManager.ManageHoldersFlags int flags, @NonNull IRoleManagerCallback callback) {
        mRemoteService.scheduleRequest(new OnAddRoleHolderRequest(mRemoteService, roleName,
                packageName, flags, callback));
    }

    /**
     * @see RoleControllerService#onRemoveRoleHolder(String, String, int, RoleManagerCallback)
     */
    public void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName,
            @RoleManager.ManageHoldersFlags int flags, @NonNull IRoleManagerCallback callback) {
        mRemoteService.scheduleRequest(new OnRemoveRoleHolderRequest(mRemoteService, roleName,
                packageName, flags, callback));
    }

    /**
     * @see RoleControllerService#onClearRoleHolders(String, int, RoleManagerCallback)
     */
    public void onClearRoleHolders(@NonNull String roleName,
            @RoleManager.ManageHoldersFlags int flags, @NonNull IRoleManagerCallback callback) {
        mRemoteService.scheduleRequest(new OnClearRoleHoldersRequest(mRemoteService, roleName,
                flags, callback));
    }

    /**
     * @see RoleControllerService#onSmsKillSwitchToggled(boolean)
     */
    public void onSmsKillSwitchToggled(boolean enabled) {
        mRemoteService.scheduleAsyncRequest(new OnSmsKillSwitchToggledRequest(enabled));
    }

    /**
     * Connection to the remote service.
     */
    private static final class RemoteService extends AbstractMultiplePendingRequestsRemoteService<
            RemoteService, IRoleController> {

        private static final long UNBIND_DELAY_MILLIS = 15 * 1000;
        private static final long REQUEST_TIMEOUT_MILLIS = 15 * 1000;

        /**
         * Create a connection to the remote service
         *
         * @param context the context to use
         * @param componentName the component of the service to connect to
         * @param handler the handler for binding service and callbacks
         * @param userId the user whom remote service should be connected as
         */
        RemoteService(@NonNull Context context, @NonNull ComponentName componentName,
                @NonNull Handler handler, @UserIdInt int userId) {
            super(context, RoleControllerService.SERVICE_INTERFACE, componentName, userId,
                    service -> Log.e(LOG_TAG, "RemoteService " + service + " died"), handler, false,
                    false, 1);
        }

        /**
         * @return The default handler used by this service.
         */
        @NonNull
        public Handler getHandler() {
            return mHandler;
        }

        @Override
        protected @NonNull IRoleController getServiceInterface(@NonNull IBinder binder) {
            return IRoleController.Stub.asInterface(binder);
        }

        @Override
        protected long getTimeoutIdleBindMillis() {
            return UNBIND_DELAY_MILLIS;
        }

        @Override
        protected long getRemoteRequestMillis() {
            return REQUEST_TIMEOUT_MILLIS;
        }

        @Override
        public void scheduleRequest(
                @NonNull BasePendingRequest<RemoteService, IRoleController> pendingRequest) {
            super.scheduleRequest(pendingRequest);
        }

        @Override
        public void scheduleAsyncRequest(@NonNull AsyncRequest<IRoleController> request) {
            super.scheduleAsyncRequest(request);
        }
    }

    /**
     * Request for {@link #onGrantDefaultRoles(IRoleManagerCallback)}.
     */
    private static final class OnGrantDefaultRolesRequest
            extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {

        @NonNull
        private final IRoleManagerCallback mCallback;

        @NonNull
        private final IRoleManagerCallback mRemoteCallback;

        private OnGrantDefaultRolesRequest(@NonNull RemoteService service,
                @NonNull IRoleManagerCallback callback) {
            super(service);

            mCallback = callback;

            mRemoteCallback = new IRoleManagerCallback.Stub() {
                @Override
                public void onSuccess() throws RemoteException {
                    long token = Binder.clearCallingIdentity();
                    try {
                        mCallback.onSuccess();
                    } finally {
                        Binder.restoreCallingIdentity(token);
                        finish();
                    }
                }
                @Override
                public void onFailure() throws RemoteException {
                    long token = Binder.clearCallingIdentity();
                    try {
                        mCallback.onSuccess();
                    } finally {
                        Binder.restoreCallingIdentity(token);
                        finish();
                    }
                }
            };
        }

        @Override
        protected void onTimeout(@NonNull RemoteService remoteService) {
            try {
                mCallback.onFailure();
            } catch (RemoteException e) {
                Log.e(LOG_TAG, "Error calling onFailure() on callback", e);
            }
        }

        @Override
        public void run() {
            try {
                getService().getServiceInterface().onGrantDefaultRoles(mRemoteCallback);
            } catch (RemoteException e) {
                Log.e(LOG_TAG, "Error calling onGrantDefaultRoles()", e);
            }
        }
    }

    /**
     * Request for {@link #onAddRoleHolder(String, String, int, IRoleManagerCallback)}.
     */
    private static final class OnAddRoleHolderRequest
            extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {

        @NonNull
        private final String mRoleName;
        @NonNull
        private final String mPackageName;
        @RoleManager.ManageHoldersFlags
        private final int mFlags;
        @NonNull
        private final IRoleManagerCallback mCallback;

        @NonNull
        private final IRoleManagerCallback mRemoteCallback;

        private OnAddRoleHolderRequest(@NonNull RemoteService service, @NonNull String roleName,
                @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags,
                @NonNull IRoleManagerCallback callback) {
            super(service);

            mRoleName = roleName;
            mPackageName = packageName;
            mFlags = flags;
            mCallback = callback;

            mRemoteCallback = new IRoleManagerCallback.Stub() {
                @Override
                public void onSuccess() throws RemoteException {
                    long token = Binder.clearCallingIdentity();
                    try {
                        mCallback.onSuccess();
                    } finally {
                        Binder.restoreCallingIdentity(token);
                        finish();
                    }
                }
                @Override
                public void onFailure() throws RemoteException {
                    long token = Binder.clearCallingIdentity();
                    try {
                        mCallback.onSuccess();
                    } finally {
                        Binder.restoreCallingIdentity(token);
                        finish();
                    }
                }
            };
        }

        @Override
        protected void onTimeout(@NonNull RemoteService remoteService) {
            try {
                mCallback.onFailure();
            } catch (RemoteException e) {
                Log.e(LOG_TAG, "Error calling onFailure() on callback", e);
            }
        }

        @Override
        public void run() {
            try {
                getService().getServiceInterface().onAddRoleHolder(mRoleName, mPackageName, mFlags,
                        mRemoteCallback);
            } catch (RemoteException e) {
                Log.e(LOG_TAG, "Error calling onAddRoleHolder()", e);
            }
        }
    }

    /**
     * Request for {@link #onRemoveRoleHolder(String, String, int, IRoleManagerCallback)}.
     */
    private static final class OnRemoveRoleHolderRequest
            extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {

        @NonNull
        private final String mRoleName;
        @NonNull
        private final String mPackageName;
        @RoleManager.ManageHoldersFlags
        private final int mFlags;
        @NonNull
        private final IRoleManagerCallback mCallback;

        @NonNull
        private final IRoleManagerCallback mRemoteCallback;

        private OnRemoveRoleHolderRequest(@NonNull RemoteService service, @NonNull String roleName,
                @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags,
                @NonNull IRoleManagerCallback callback) {
            super(service);

            mRoleName = roleName;
            mPackageName = packageName;
            mFlags = flags;
            mCallback = callback;

            mRemoteCallback = new IRoleManagerCallback.Stub() {
                @Override
                public void onSuccess() throws RemoteException {
                    long token = Binder.clearCallingIdentity();
                    try {
                        mCallback.onSuccess();
                    } finally {
                        Binder.restoreCallingIdentity(token);
                        finish();
                    }
                }
                @Override
                public void onFailure() throws RemoteException {
                    long token = Binder.clearCallingIdentity();
                    try {
                        mCallback.onSuccess();
                    } finally {
                        Binder.restoreCallingIdentity(token);
                        finish();
                    }
                }
            };
        }

        @Override
        protected void onTimeout(@NonNull RemoteService remoteService) {
            try {
                mCallback.onFailure();
            } catch (RemoteException e) {
                Log.e(LOG_TAG, "Error calling onFailure() on callback", e);
            }
        }

        @Override
        public void run() {
            try {
                getService().getServiceInterface().onRemoveRoleHolder(mRoleName, mPackageName,
                        mFlags, mRemoteCallback);
            } catch (RemoteException e) {
                Log.e(LOG_TAG, "Error calling onRemoveRoleHolder()", e);
            }
        }
    }

    /**
     * Request for {@link #onClearRoleHolders(String, int, IRoleManagerCallback)}.
     */
    private static final class OnClearRoleHoldersRequest
            extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> {

        @NonNull
        private final String mRoleName;
        @RoleManager.ManageHoldersFlags
        private final int mFlags;
        @NonNull
        private final IRoleManagerCallback mCallback;

        @NonNull
        private final IRoleManagerCallback mRemoteCallback;

        private OnClearRoleHoldersRequest(@NonNull RemoteService service, @NonNull String roleName,
                @RoleManager.ManageHoldersFlags int flags, @NonNull IRoleManagerCallback callback) {
            super(service);

            mRoleName = roleName;
            mFlags = flags;
            mCallback = callback;

            mRemoteCallback = new IRoleManagerCallback.Stub() {
                @Override
                public void onSuccess() throws RemoteException {
                    long token = Binder.clearCallingIdentity();
                    try {
                        mCallback.onSuccess();
                    } finally {
                        Binder.restoreCallingIdentity(token);
                        finish();
                    }
                }
                @Override
                public void onFailure() throws RemoteException {
                    long token = Binder.clearCallingIdentity();
                    try {
                        mCallback.onSuccess();
                    } finally {
                        Binder.restoreCallingIdentity(token);
                        finish();
                    }
                }
            };
        }

        @Override
        protected void onTimeout(@NonNull RemoteService remoteService) {
            try {
                mCallback.onFailure();
            } catch (RemoteException e) {
                Log.e(LOG_TAG, "Error calling onFailure() on callback", e);
            }
        }

        @Override
        public void run() {
            try {
                getService().getServiceInterface().onClearRoleHolders(mRoleName, mFlags,
                        mRemoteCallback);
            } catch (RemoteException e) {
                Log.e(LOG_TAG, "Error calling onClearRoleHolders()", e);
            }
        }
    }

    /**
     * Request for {@link #onSmsKillSwitchToggled(boolean)}
     */
    private static final class OnSmsKillSwitchToggledRequest
            implements AbstractRemoteService.AsyncRequest<IRoleController> {

        private final boolean mEnabled;

        private OnSmsKillSwitchToggledRequest(boolean enabled) {
            mEnabled = enabled;
        }

        @Override
        public void run(@NonNull IRoleController service) {
            try {
                service.onSmsKillSwitchToggled(mEnabled);
            } catch (RemoteException e) {
                Log.e(LOG_TAG, "Error calling onSmsKillSwitchToggled()", e);
            }
        }
    }
}
Loading