diff options
20 files changed, 584 insertions, 427 deletions
diff --git a/Android.bp b/Android.bp index fb6ff0fb6dbc..3475ed788a3a 100644 --- a/Android.bp +++ b/Android.bp @@ -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", diff --git a/api/system-current.txt b/api/system-current.txt index 9d6c27f72b2f..e501864f2ec4 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -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 { diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 1faa2ac76d71..90bc0a6dd11e 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -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 diff --git a/core/java/android/rolecontrollerservice/IRoleControllerService.aidl b/core/java/android/app/role/IRoleController.aidl index 40852ea9719d..07a4161af771 100644 --- a/core/java/android/rolecontrollerservice/IRoleControllerService.aidl +++ b/core/java/android/app/role/IRoleController.aidl @@ -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); } diff --git a/core/java/android/app/role/RoleControllerManager.java b/core/java/android/app/role/RoleControllerManager.java new file mode 100644 index 000000000000..a9b13ee8c2fc --- /dev/null +++ b/core/java/android/app/role/RoleControllerManager.java @@ -0,0 +1,474 @@ +/* + * 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); + } + } + } +} diff --git a/core/java/android/rolecontrollerservice/RoleControllerService.java b/core/java/android/app/role/RoleControllerService.java index c846b076c14f..f3da3580cbc6 100644 --- a/core/java/android/rolecontrollerservice/RoleControllerService.java +++ b/core/java/android/app/role/RoleControllerService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * 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. @@ -14,15 +14,12 @@ * limitations under the License. */ -package android.rolecontrollerservice; +package android.app.role; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.app.Service; -import android.app.role.IRoleManagerCallback; -import android.app.role.RoleManager; -import android.app.role.RoleManagerCallback; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; @@ -48,17 +45,21 @@ public abstract class RoleControllerService extends Service { private static final String LOG_TAG = RoleControllerService.class.getSimpleName(); /** - * The {@link Intent} that must be declared as handled by the service. The service should also - * require the {@link android.Manifest.permission#BIND_ROLE_CONTROLLER_SERVICE} permission so - * that other applications can not abuse it. + * The {@link Intent} that must be declared as handled by the service. */ - public static final String SERVICE_INTERFACE = - "android.rolecontrollerservice.RoleControllerService"; + public static final String SERVICE_INTERFACE = "android.app.role.RoleControllerService"; @Nullable @Override public final IBinder onBind(@Nullable Intent intent) { - return new IRoleControllerService.Stub() { + return new IRoleController.Stub() { + + @Override + public void onGrantDefaultRoles(IRoleManagerCallback callback) { + Preconditions.checkNotNull(callback, "callback cannot be null"); + RoleControllerService.this.onGrantDefaultRoles(new RoleManagerCallbackDelegate( + callback)); + } @Override public void onAddRoleHolder(String roleName, String packageName, int flags, @@ -92,13 +93,6 @@ public abstract class RoleControllerService extends Service { } @Override - public void onGrantDefaultRoles(IRoleManagerCallback callback) { - Preconditions.checkNotNull(callback, "callback cannot be null"); - RoleControllerService.this.onGrantDefaultRoles(new RoleManagerCallbackDelegate( - callback)); - } - - @Override public void onSmsKillSwitchToggled(boolean smsRestrictionEnabled) { RoleControllerService.this.onSmsKillSwitchToggled(smsRestrictionEnabled); } @@ -106,6 +100,16 @@ public abstract class RoleControllerService extends Service { } /** + * Called by system to grant default permissions and roles. + * <p> + * This is typically when creating a new user or upgrading either system or + * permission controller package + * + * @param callback the callback for whether this call is successful + */ + public abstract void onGrantDefaultRoles(@NonNull RoleManagerCallback callback); + + /** * Add a specific application to the holders of a role. If the role is exclusive, the previous * holder will be replaced. * <p> @@ -153,20 +157,10 @@ public abstract class RoleControllerService extends Service { /** * Cleanup appop/permissions state in response to sms kill switch toggle * - * @param smsRestrictionEnabled whether kill switch was turned on + * @param enabled whether kill switch was turned on */ //STOPSHIP: remove this api before shipping a final version - public abstract void onSmsKillSwitchToggled(boolean smsRestrictionEnabled); - - /** - * Called by system to grant default permissions and roles. - * <p> - * This is typically when creating a new user or upgrading either system or - * permission controller package - * - * @param callback the callback for whether this call is successful - */ - public abstract void onGrantDefaultRoles(@NonNull RoleManagerCallback callback); + public abstract void onSmsKillSwitchToggled(boolean enabled); private static class RoleManagerCallbackDelegate implements RoleManagerCallback { diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java index f91d8780084f..a663498d9057 100644 --- a/core/java/android/app/role/RoleManager.java +++ b/core/java/android/app/role/RoleManager.java @@ -545,7 +545,7 @@ public final class RoleManager { /** * Set the names of all the available roles. Should only be called from - * {@link android.rolecontrollerservice.RoleControllerService}. + * {@link android.app.role.RoleControllerService}. * <p> * <strong>Note:</strong> Using this API requires holding * {@link #PERMISSION_MANAGE_ROLES_FROM_CONTROLLER}. @@ -569,7 +569,7 @@ public final class RoleManager { /** * Add a specific application to the holders of a role, only modifying records inside * {@link RoleManager}. Should only be called from - * {@link android.rolecontrollerservice.RoleControllerService}. + * {@link android.app.role.RoleControllerService}. * <p> * <strong>Note:</strong> Using this API requires holding * {@link #PERMISSION_MANAGE_ROLES_FROM_CONTROLLER}. @@ -602,7 +602,7 @@ public final class RoleManager { /** * Remove a specific application from the holders of a role, only modifying records inside * {@link RoleManager}. Should only be called from - * {@link android.rolecontrollerservice.RoleControllerService}. + * {@link android.app.role.RoleControllerService}. * <p> * <strong>Note:</strong> Using this API requires holding * {@link #PERMISSION_MANAGE_ROLES_FROM_CONTROLLER}. diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index f28718cadad1..f896274ed8b3 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3176,6 +3176,7 @@ public abstract class Context { RESTRICTIONS_SERVICE, APP_OPS_SERVICE, ROLE_SERVICE, + //@hide ROLE_CONTROLLER_SERVICE, CAMERA_SERVICE, PRINT_SERVICE, CONSUMER_IR_SERVICE, @@ -4285,6 +4286,16 @@ public abstract class Context { public static final String ROLE_SERVICE = "role"; /** + * Official published name of the (internal) role controller service. + * + * @see #getSystemService(String) + * @see android.app.role.RoleControllerService + * + * @hide + */ + public static final String ROLE_CONTROLLER_SERVICE = "role_controller"; + + /** * Use with {@link #getSystemService(String)} to retrieve a * {@link android.hardware.camera2.CameraManager} for interacting with * camera devices. diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java index 5695e42bef8e..2379928f8946 100644 --- a/core/java/android/permission/PermissionControllerManager.java +++ b/core/java/android/permission/PermissionControllerManager.java @@ -513,7 +513,8 @@ public final class PermissionControllerManager { RemoteService(@NonNull Context context, @NonNull ComponentName componentName, @NonNull UserHandle user) { super(context, SERVICE_INTERFACE, componentName, user.getIdentifier(), - service -> Log.e(TAG, "RemoteService " + service + " died"), false, false, 1); + service -> Log.e(TAG, "RemoteService " + service + " died"), + context.getMainThreadHandler(), false, false, 1); } /** diff --git a/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java b/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java index 293ffd34da8d..37f61bf650c7 100644 --- a/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java +++ b/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java @@ -19,6 +19,7 @@ package com.android.internal.infra; import android.annotation.NonNull; import android.content.ComponentName; import android.content.Context; +import android.os.Handler; import android.os.IInterface; import android.util.Slog; @@ -43,10 +44,10 @@ public abstract class AbstractMultiplePendingRequestsRemoteService<S public AbstractMultiplePendingRequestsRemoteService(@NonNull Context context, @NonNull String serviceInterface, @NonNull ComponentName componentName, int userId, - @NonNull VultureCallback<S> callback, boolean bindInstantServiceAllowed, - boolean verbose, int initialCapacity) { - super(context, serviceInterface, componentName, userId, callback, bindInstantServiceAllowed, - verbose); + @NonNull VultureCallback<S> callback, @NonNull Handler handler, + boolean bindInstantServiceAllowed, boolean verbose, int initialCapacity) { + super(context, serviceInterface, componentName, userId, callback, handler, + bindInstantServiceAllowed, verbose); mInitialCapacity = initialCapacity; } diff --git a/core/java/com/android/internal/infra/AbstractRemoteService.java b/core/java/com/android/internal/infra/AbstractRemoteService.java index 7270302f04bb..2e709de5ad53 100644 --- a/core/java/com/android/internal/infra/AbstractRemoteService.java +++ b/core/java/com/android/internal/infra/AbstractRemoteService.java @@ -28,7 +28,6 @@ import android.os.Handler; import android.os.IBinder; import android.os.IBinder.DeathRecipient; import android.os.IInterface; -import android.os.Looper; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; @@ -114,14 +113,14 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I // NOTE: must be package-protected so this class is not extended outside AbstractRemoteService(@NonNull Context context, @NonNull String serviceInterface, @NonNull ComponentName componentName, int userId, @NonNull VultureCallback<S> callback, - boolean bindInstantServiceAllowed, boolean verbose) { + @NonNull Handler handler, boolean bindInstantServiceAllowed, boolean verbose) { mContext = context; mVultureCallback = callback; mVerbose = verbose; mComponentName = componentName; mIntent = new Intent(serviceInterface).setComponent(mComponentName); mUserId = userId; - mHandler = new Handler(Looper.getMainLooper()); + mHandler = new Handler(handler.getLooper()); mBindInstantServiceAllowed = bindInstantServiceAllowed; } diff --git a/core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java b/core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java index 3e92a0b196ee..a70fc3e17d60 100644 --- a/core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java +++ b/core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java @@ -19,6 +19,7 @@ package com.android.internal.infra; import android.annotation.NonNull; import android.content.ComponentName; import android.content.Context; +import android.os.Handler; import android.os.IInterface; import android.util.Slog; @@ -42,10 +43,10 @@ public abstract class AbstractSinglePendingRequestRemoteService<S public AbstractSinglePendingRequestRemoteService(@NonNull Context context, @NonNull String serviceInterface, @NonNull ComponentName componentName, int userId, - @NonNull VultureCallback<S> callback, boolean bindInstantServiceAllowed, - boolean verbose) { - super(context, serviceInterface, componentName, userId, callback, bindInstantServiceAllowed, - verbose); + @NonNull VultureCallback<S> callback, @NonNull Handler handler, + boolean bindInstantServiceAllowed, boolean verbose) { + super(context, serviceInterface, componentName, userId, callback, handler, + bindInstantServiceAllowed, verbose); } @Override // from AbstractRemoteService diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 5d24ebce78e3..d176260a9896 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3049,12 +3049,6 @@ <permission android:name="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE" android:protectionLevel="signature" /> - <!-- Must be required by the RoleControllerService to ensure that only the system can bind to - it. - @hide --> - <permission android:name="android.permission.BIND_ROLE_CONTROLLER_SERVICE" - android:protectionLevel="signature" /> - <!-- @SystemApi Must be required by the RuntimePermissionPresenterService to ensure that only the system can bind to it. @hide --> diff --git a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java index 45ea86f9e74e..922b3271e20c 100644 --- a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java +++ b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java @@ -46,7 +46,8 @@ public class RemoteAppPredictionService extends ComponentName componentName, int userId, RemoteAppPredictionServiceCallbacks callback, boolean bindInstantServiceAllowed, boolean verbose) { - super(context, serviceInterface, componentName, userId, callback, bindInstantServiceAllowed, + super(context, serviceInterface, componentName, userId, callback, + context.getMainThreadHandler(), bindInstantServiceAllowed, verbose, /* initialCapacity= */ 1); } diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java index a38c3cf9975e..aaba1edc73d6 100644 --- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java +++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java @@ -55,7 +55,7 @@ final class RemoteAugmentedAutofillService boolean bindInstantServiceAllowed, boolean verbose, int idleUnbindTimeoutMs, int requestTimeoutMs) { super(context, AugmentedAutofillService.SERVICE_INTERFACE, serviceName, userId, callbacks, - bindInstantServiceAllowed, verbose); + context.getMainThreadHandler(), bindInstantServiceAllowed, verbose); mIdleUnbindTimeoutMs = idleUnbindTimeoutMs; mRequestTimeoutMs = requestTimeoutMs; diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java index e8a52b4a12a9..b8a7d44a4d10 100644 --- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java +++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java @@ -64,7 +64,7 @@ final class RemoteFillService RemoteFillService(Context context, ComponentName componentName, int userId, FillServiceCallbacks callbacks, boolean bindInstantServiceAllowed) { super(context, AutofillService.SERVICE_INTERFACE, componentName, userId, callbacks, - bindInstantServiceAllowed, sVerbose); + context.getMainThreadHandler(), bindInstantServiceAllowed, sVerbose); mCallbacks = callbacks; } diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java index f7ac7b8c61b2..1d2d6254f759 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java +++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java @@ -46,7 +46,8 @@ final class RemoteContentCaptureService ContentCaptureServiceCallbacks callbacks, boolean bindInstantServiceAllowed, boolean verbose, int idleUnbindTimeoutMs) { super(context, serviceInterface, serviceComponentName, userId, callbacks, - bindInstantServiceAllowed, verbose, /* initialCapacity= */ 2); + context.getMainThreadHandler(), bindInstantServiceAllowed, verbose, + /* initialCapacity= */ 2); mServerCallback = callback.asBinder(); mIdleUnbindTimeoutMs = idleUnbindTimeoutMs; diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/RemoteContentSuggestionsService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/RemoteContentSuggestionsService.java index bf48d7623255..442972a1e477 100644 --- a/services/contentsuggestions/java/com/android/server/contentsuggestions/RemoteContentSuggestionsService.java +++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/RemoteContentSuggestionsService.java @@ -47,7 +47,8 @@ public class RemoteContentSuggestionsService extends int userId, Callbacks callbacks, boolean bindInstantServiceAllowed, boolean verbose) { super(context, ContentSuggestionsService.SERVICE_INTERFACE, serviceName, userId, callbacks, - bindInstantServiceAllowed, verbose, /* initialCapacity= */ 1); + context.getMainThreadHandler(), bindInstantServiceAllowed, verbose, + /* initialCapacity= */ 1); } @Override diff --git a/services/core/java/com/android/server/role/RemoteRoleControllerService.java b/services/core/java/com/android/server/role/RemoteRoleControllerService.java deleted file mode 100644 index 4fb40db8597c..000000000000 --- a/services/core/java/com/android/server/role/RemoteRoleControllerService.java +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright (C) 2018 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 com.android.server.role; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.UserIdInt; -import android.annotation.WorkerThread; -import android.app.role.IRoleManagerCallback; -import android.app.role.RoleManager; -import android.app.role.RoleManagerCallback; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.UserHandle; -import android.rolecontrollerservice.IRoleControllerService; -import android.rolecontrollerservice.RoleControllerService; -import android.util.Log; -import android.util.Slog; - -import com.android.internal.util.function.pooled.PooledLambda; -import com.android.server.FgThread; - -import java.util.ArrayDeque; -import java.util.Arrays; -import java.util.Queue; - -/** - * Handles connection with {@link RoleControllerService}. - */ -public class RemoteRoleControllerService { - - static final boolean DEBUG = false; - private static final String LOG_TAG = RemoteRoleControllerService.class.getSimpleName(); - - @NonNull - private final Connection mConnection; - - public RemoteRoleControllerService(@UserIdInt int userId, @NonNull Context context) { - mConnection = new Connection(userId, context); - } - - /** - * Add a specific application to the holders of a role. If the role is exclusive, the previous - * holder will be replaced. - * - * @see RoleControllerService#onAddRoleHolder(String, String, int, RoleManagerCallback) - */ - public void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName, - @RoleManager.ManageHoldersFlags int flags, @NonNull IRoleManagerCallback callback) { - mConnection.enqueueCall(new Connection.Call((service, callbackDelegate) -> - service.onAddRoleHolder(roleName, packageName, flags, callbackDelegate), callback)); - } - - /** - * Remove a specific application from the holders of a role. - * - * @see RoleControllerService#onRemoveRoleHolder(String, String, int, RoleManagerCallback) - */ - public void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName, - @RoleManager.ManageHoldersFlags int flags, @NonNull IRoleManagerCallback callback) { - mConnection.enqueueCall(new Connection.Call((service, callbackDelegate) -> - service.onRemoveRoleHolder(roleName, packageName, flags, callbackDelegate), - callback)); - } - - /** - * Remove all holders of a role. - * - * @see RoleControllerService#onClearRoleHolders(String, int, RoleManagerCallback) - */ - public void onClearRoleHolders(@NonNull String roleName, - @RoleManager.ManageHoldersFlags int flags, @NonNull IRoleManagerCallback callback) { - mConnection.enqueueCall(new Connection.Call((service, callbackDelegate) -> - service.onClearRoleHolders(roleName, flags, callbackDelegate), callback)); - } - - /** - * Performs granting of default roles and permissions and appops - * - * @see RoleControllerService#onGrantDefaultRoles(RoleManagerCallback) - */ - public void onGrantDefaultRoles(@NonNull IRoleManagerCallback callback) { - mConnection.enqueueCall(new Connection.Call(IRoleControllerService::onGrantDefaultRoles, - callback)); - } - - /** - * @see RoleControllerService#onSmsKillSwitchToggled(boolean) - */ - public void onSmsKillSwitchToggled(boolean smsRestrictionEnabled) { - mConnection.enqueueCall(new Connection.Call( - (s, cb) -> s.onSmsKillSwitchToggled(smsRestrictionEnabled), - new IRoleManagerCallback.Default() { - @Override - public void onFailure() { - Slog.e(LOG_TAG, "Failed onSmsKillSwitchToggled"); - } - })); - } - - private static final class Connection implements ServiceConnection { - - private static final long UNBIND_DELAY_MILLIS = 15 * 1000; - - @UserIdInt - private final int mUserId; - - @NonNull - private final Context mContext; - - @NonNull - private final Handler mHandler = FgThread.getHandler(); - - private boolean mBound; - - @Nullable - private IRoleControllerService mService; - - @NonNull - private final Queue<Call> mPendingCalls = new ArrayDeque<>(); - - @NonNull - private final Runnable mUnbindRunnable = this::unbind; - - Connection(@UserIdInt int userId, @NonNull Context context) { - mUserId = userId; - mContext = context; - } - - @Override - @WorkerThread - public void onServiceConnected(@NonNull ComponentName name, @NonNull IBinder service) { - mService = IRoleControllerService.Stub.asInterface(service); - executePendingCalls(); - } - - @WorkerThread - private void executePendingCalls() { - while (!mPendingCalls.isEmpty()) { - Call call = mPendingCalls.poll(); - call.execute(mService); - } - scheduleUnbind(); - } - - @Override - @WorkerThread - public void onServiceDisconnected(@NonNull ComponentName name) { - mService = null; - } - - @Override - @WorkerThread - public void onBindingDied(@NonNull ComponentName name) { - unbind(); - } - - public void enqueueCall(@NonNull Call call) { - if (DEBUG) { - Slog.i(LOG_TAG, "Enqueue " + call); - } - mHandler.executeOrSendMessage(PooledLambda.obtainMessage(Connection::executeCall, this, - call)); - } - - @WorkerThread - private void executeCall(@NonNull Call call) { - ensureBound(); - if (mService == null) { - if (DEBUG) { - Slog.i(LOG_TAG, "Delaying until service connected: " + call); - } - mPendingCalls.offer(call); - return; - } - call.execute(mService); - scheduleUnbind(); - } - - @WorkerThread - private void ensureBound() { - mHandler.removeCallbacks(mUnbindRunnable); - if (!mBound) { - Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE); - intent.setPackage(mContext.getPackageManager() - .getPermissionControllerPackageName()); - // Use direct handler to ensure onServiceConnected callback happens in the same - // call frame, as required by onGrantDefaultRoles - // - // Note that as a result, onServiceConnected may happen not on main thread! - mBound = mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE, - mHandler, UserHandle.of(mUserId)); - } - } - - private void scheduleUnbind() { - mHandler.removeCallbacks(mUnbindRunnable); - mHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS); - } - - @WorkerThread - private void unbind() { - if (mBound) { - mService = null; - mContext.unbindService(this); - mBound = false; - } - } - - public static class Call { - - private static final int TIMEOUT_MILLIS = 15 * 1000; - - @NonNull - private final CallExecutor mCallExecutor; - - @NonNull - private final IRoleManagerCallback mCallback; - - @NonNull - private final Handler mHandler = FgThread.getHandler(); - - @NonNull - private final Runnable mTimeoutRunnable = this::notifyTimeout; - - private boolean mCallbackNotified; - - @Nullable - private final String mDebugName; - - private Call(@NonNull CallExecutor callExecutor, - @NonNull IRoleManagerCallback callback) { - mCallExecutor = callExecutor; - mCallback = callback; - mDebugName = DEBUG - ? Arrays.stream(Thread.currentThread().getStackTrace()) - .filter(s -> s.getClassName().equals( - RemoteRoleControllerService.class.getName())) - .findFirst() - .get() - .getMethodName() - : null; - } - - @WorkerThread - public void execute(IRoleControllerService service) { - if (DEBUG) { - Slog.i(LOG_TAG, "Executing " + this); - } - try { - mHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MILLIS); - mCallExecutor.execute(service, new CallbackDelegate()); - } catch (RemoteException e) { - Slog.e(LOG_TAG, "Error calling RoleControllerService", e); - notifyCallback(false); - } - } - - @WorkerThread - private void notifyTimeout() { - Slog.e(LOG_TAG, "Call timed out, calling onFailure()"); - notifyCallback(false); - } - - @WorkerThread - private void notifyCallback(boolean success) { - if (DEBUG) { - Log.i(LOG_TAG, "notifyCallback(" + this - + ", success = " + success + ")"); - } - if (mCallbackNotified) { - return; - } - mCallbackNotified = true; - mHandler.removeCallbacks(mTimeoutRunnable); - try { - if (success) { - mCallback.onSuccess(); - } else { - mCallback.onFailure(); - } - } catch (RemoteException e) { - Slog.e(LOG_TAG, "Error calling " + (success ? "onSuccess()" : "onFailure()") - + " callback", e); - } - } - - @Override - public String toString() { - return DEBUG ? mDebugName : "Call with callback: " + mCallback; - } - - @FunctionalInterface - public interface CallExecutor { - - @WorkerThread - void execute(IRoleControllerService service, IRoleManagerCallback callbackDelegate) - throws RemoteException; - } - - private class CallbackDelegate extends IRoleManagerCallback.Stub { - - @Override - public void onSuccess() throws RemoteException { - mHandler.sendMessage(PooledLambda.obtainMessage(Call::notifyCallback, Call.this, - true)); - } - - @Override - public void onFailure() throws RemoteException { - mHandler.sendMessage(PooledLambda.obtainMessage(Call::notifyCallback, Call.this, - false)); - } - } - } - } -} diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java index f533ad167761..2538226cc74a 100644 --- a/services/core/java/com/android/server/role/RoleManagerService.java +++ b/services/core/java/com/android/server/role/RoleManagerService.java @@ -28,6 +28,7 @@ import android.app.AppOpsManager; import android.app.role.IOnRoleHoldersChangedListener; import android.app.role.IRoleManager; import android.app.role.IRoleManagerCallback; +import android.app.role.RoleControllerManager; import android.app.role.RoleManager; import android.content.BroadcastReceiver; import android.content.Context; @@ -97,6 +98,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C private static final String LOG_TAG = RoleManagerService.class.getSimpleName(); + private static final boolean DEBUG = false; + @NonNull private final UserManagerInternal mUserManagerInternal; @NonNull @@ -123,12 +126,11 @@ public class RoleManagerService extends SystemService implements RoleUserState.C private final SparseArray<RoleUserState> mUserStates = new SparseArray<>(); /** - * Maps user id to its controller service. + * Maps user id to its controller. */ @GuardedBy("mLock") @NonNull - private final SparseArray<RemoteRoleControllerService> mControllerServices = - new SparseArray<>(); + private final SparseArray<RoleControllerManager> mControllers = new SparseArray<>(); /** * Maps user id to its list of listeners. @@ -190,9 +192,9 @@ public class RoleManagerService extends SystemService implements RoleUserState.C @Override public void onReceive(Context context, Intent intent) { int userId = UserHandle.getUserId(intent.getIntExtra(Intent.EXTRA_UID, -1)); - if (RemoteRoleControllerService.DEBUG) { - Slog.i(LOG_TAG, - "Packages changed - re-running initial grants for user " + userId); + if (DEBUG) { + Slog.i(LOG_TAG, "Packages changed - re-running initial grants for user " + + userId); } performInitialGrantsIfNecessary(userId); } @@ -260,7 +262,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C } catch (InterruptedException | ExecutionException | TimeoutException e) { Slog.e(LOG_TAG, "Failed to grant defaults for user " + userId, e); } - } else if (RemoteRoleControllerService.DEBUG) { + } else if (DEBUG) { Slog.i(LOG_TAG, "Already ran grants for package state " + packagesHash); } } @@ -326,14 +328,22 @@ public class RoleManagerService extends SystemService implements RoleUserState.C } @NonNull - private RemoteRoleControllerService getOrCreateControllerService(@UserIdInt int userId) { + private RoleControllerManager getOrCreateControllerService(@UserIdInt int userId) { synchronized (mLock) { - RemoteRoleControllerService controllerService = mControllerServices.get(userId); - if (controllerService == null) { - controllerService = new RemoteRoleControllerService(userId, getContext()); - mControllerServices.put(userId, controllerService); + RoleControllerManager controller = mControllers.get(userId); + if (controller == null) { + Context systemContext = getContext(); + Context context; + try { + context = systemContext.createPackageContextAsUser( + systemContext.getPackageName(), 0, UserHandle.of(userId)); + } catch (NameNotFoundException e) { + throw new RuntimeException(e); + } + controller = new RoleControllerManager(context, FgThread.getHandler()); + mControllers.put(userId, controller); } - return controllerService; + return controller; } } @@ -362,7 +372,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C RoleUserState userState; synchronized (mLock) { listeners = mListeners.removeReturnOld(userId); - mControllerServices.remove(userId); + mControllers.remove(userId); userState = mUserStates.removeReturnOld(userId); } if (listeners != null) { |