Loading Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -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", Loading Loading @@ -275,7 +276,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", Loading api/system-current.txt +11 −15 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -6177,21 +6188,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 { Loading core/java/android/app/SystemServiceRegistry.java +9 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading core/java/android/rolecontrollerservice/IRoleControllerService.aidl→core/java/android/app/role/IRoleController.aidl +5 −5 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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); } core/java/android/app/role/RoleControllerManager.java 0 → 100644 +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
Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -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", Loading Loading @@ -275,7 +276,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", Loading
api/system-current.txt +11 −15 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -6177,21 +6188,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 { Loading
core/java/android/app/SystemServiceRegistry.java +9 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading
core/java/android/rolecontrollerservice/IRoleControllerService.aidl→core/java/android/app/role/IRoleController.aidl +5 −5 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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); }
core/java/android/app/role/RoleControllerManager.java 0 → 100644 +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); } } } }