Loading core/java/android/app/role/RoleControllerManager.java +98 −402 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemService; import android.annotation.UserIdInt; import android.app.ActivityThread; import android.content.ComponentName; import android.content.Context; Loading @@ -29,18 +28,18 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.RemoteCallback; 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; import com.android.internal.infra.AndroidFuture; import com.android.internal.infra.ServiceConnector; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; /** Loading @@ -53,6 +52,8 @@ public class RoleControllerManager { private static final String LOG_TAG = RoleControllerManager.class.getSimpleName(); private static final long REQUEST_TIMEOUT_MILLIS = 15 * 1000; private static volatile ComponentName sRemoteServiceComponentName; private static final Object sRemoteServicesLock = new Object(); Loading @@ -61,10 +62,11 @@ public class RoleControllerManager { * Global remote services (per user) used by all {@link RoleControllerManager managers}. */ @GuardedBy("sRemoteServicesLock") private static final SparseArray<RemoteService> sRemoteServices = new SparseArray<>(); private static final SparseArray<ServiceConnector<IRoleController>> sRemoteServices = new SparseArray<>(); @NonNull private final RemoteService mRemoteService; private final ServiceConnector<IRoleController> mRemoteService; /** * Initialize the remote service component name once so that we can avoid acquiring the Loading Loading @@ -92,10 +94,19 @@ public class RoleControllerManager { @NonNull Handler handler, @NonNull Context context) { synchronized (sRemoteServicesLock) { int userId = context.getUserId(); RemoteService remoteService = sRemoteServices.get(userId); ServiceConnector<IRoleController> remoteService = sRemoteServices.get(userId); if (remoteService == null) { remoteService = new RemoteService(ActivityThread.currentApplication(), remoteServiceComponentName, handler, userId); remoteService = new ServiceConnector.Impl<IRoleController>( ActivityThread.currentApplication(), new Intent(RoleControllerService.SERVICE_INTERFACE) .setComponent(remoteServiceComponentName), 0 /* bindingFlags */, userId, IRoleController.Stub::asInterface) { @Override protected Handler getJobHandler() { return handler; } }; sRemoteServices.put(userId, remoteService); } mRemoteService = remoteService; Loading @@ -120,8 +131,12 @@ public class RoleControllerManager { */ public void grantDefaultRoles(@NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { mRemoteService.scheduleRequest(new GrantDefaultRolesRequest(mRemoteService, executor, callback)); AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> { AndroidFuture<Bundle> future = new AndroidFuture<>(); service.grantDefaultRoles(new RemoteCallback(future::complete)); return future; }); propagateCallback(operation, "grantDefaultRoles", executor, callback); } /** Loading @@ -129,8 +144,13 @@ public class RoleControllerManager { */ public void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { mRemoteService.scheduleRequest(new OnAddRoleHolderRequest(mRemoteService, roleName, packageName, flags, callback)); AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> { AndroidFuture<Bundle> future = new AndroidFuture<>(); service.onAddRoleHolder(roleName, packageName, flags, new RemoteCallback(future::complete)); return future; }); propagateCallback(operation, "onAddRoleHolder", callback); } /** Loading @@ -138,8 +158,13 @@ public class RoleControllerManager { */ public void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { mRemoteService.scheduleRequest(new OnRemoveRoleHolderRequest(mRemoteService, roleName, packageName, flags, callback)); AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> { AndroidFuture<Bundle> future = new AndroidFuture<>(); service.onRemoveRoleHolder(roleName, packageName, flags, new RemoteCallback(future::complete)); return future; }); propagateCallback(operation, "onRemoveRoleHolder", callback); } /** Loading @@ -147,8 +172,13 @@ public class RoleControllerManager { */ public void onClearRoleHolders(@NonNull String roleName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { mRemoteService.scheduleRequest(new OnClearRoleHoldersRequest(mRemoteService, roleName, flags, callback)); AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> { AndroidFuture<Bundle> future = new AndroidFuture<>(); service.onClearRoleHolders(roleName, flags, new RemoteCallback(future::complete)); return future; }); propagateCallback(operation, "onClearRoleHolders", callback); } /** Loading @@ -157,8 +187,13 @@ public class RoleControllerManager { @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) public void isApplicationQualifiedForRole(@NonNull String roleName, @NonNull String packageName, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { mRemoteService.scheduleRequest(new IsApplicationQualifiedForRoleRequest(mRemoteService, roleName, packageName, executor, callback)); AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> { AndroidFuture<Bundle> future = new AndroidFuture<>(); service.isApplicationQualifiedForRole(roleName, packageName, new RemoteCallback(future::complete)); return future; }); propagateCallback(operation, "isApplicationQualifiedForRole", executor, callback); } /** Loading @@ -167,387 +202,48 @@ public class RoleControllerManager { @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) public void isRoleVisible(@NonNull String roleName, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { mRemoteService.scheduleRequest(new IsRoleVisibleRequest(mRemoteService, roleName, executor, callback)); } /** * 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, 0, 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 #grantDefaultRoles(Executor, Consumer)}. */ private static final class GrantDefaultRolesRequest extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> { @NonNull private final Executor mExecutor; @NonNull private final Consumer<Boolean> mCallback; @NonNull private final RemoteCallback mRemoteCallback; private GrantDefaultRolesRequest(@NonNull RemoteService service, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { super(service); mExecutor = executor; mCallback = callback; mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> { long token = Binder.clearCallingIdentity(); try { boolean successful = result != null; mCallback.accept(successful); } finally { Binder.restoreCallingIdentity(token); finish(); } })); } @Override protected void onTimeout(@NonNull RemoteService remoteService) { mExecutor.execute(() -> mCallback.accept(false)); } @Override public void run() { try { getService().getServiceInterface().grantDefaultRoles(mRemoteCallback); } catch (RemoteException e) { Log.e(LOG_TAG, "Error calling grantDefaultRoles()", e); } } @Override protected void onFailed() { mRemoteCallback.sendResult(null); } } /** * Request for {@link #onAddRoleHolder(String, String, int, RemoteCallback)}. */ 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 RemoteCallback mCallback; @NonNull private final RemoteCallback mRemoteCallback; private OnAddRoleHolderRequest(@NonNull RemoteService service, @NonNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { super(service); mRoleName = roleName; mPackageName = packageName; mFlags = flags; mCallback = callback; mRemoteCallback = new RemoteCallback(result -> { long token = Binder.clearCallingIdentity(); try { mCallback.sendResult(result); } finally { Binder.restoreCallingIdentity(token); finish(); } }); } @Override protected void onTimeout(@NonNull RemoteService remoteService) { mCallback.sendResult(null); } @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, RemoteCallback)}. */ 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 RemoteCallback mCallback; @NonNull private final RemoteCallback mRemoteCallback; private OnRemoveRoleHolderRequest(@NonNull RemoteService service, @NonNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { super(service); mRoleName = roleName; mPackageName = packageName; mFlags = flags; mCallback = callback; mRemoteCallback = new RemoteCallback(result -> { long token = Binder.clearCallingIdentity(); try { mCallback.sendResult(result); } finally { Binder.restoreCallingIdentity(token); finish(); } AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> { AndroidFuture<Bundle> future = new AndroidFuture<>(); service.isRoleVisible(roleName, new RemoteCallback(future::complete)); return future; }); propagateCallback(operation, "isRoleVisible", executor, callback); } @Override protected void onTimeout(@NonNull RemoteService remoteService) { mCallback.sendResult(null); } @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, RemoteCallback)}. */ private static final class OnClearRoleHoldersRequest extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> { @NonNull private final String mRoleName; @RoleManager.ManageHoldersFlags private final int mFlags; @NonNull private final RemoteCallback mCallback; @NonNull private final RemoteCallback mRemoteCallback; private OnClearRoleHoldersRequest(@NonNull RemoteService service, @NonNull String roleName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { super(service); mRoleName = roleName; mFlags = flags; mCallback = callback; mRemoteCallback = new RemoteCallback(result -> { private void propagateCallback(AndroidFuture<Bundle> operation, String opName, @CallbackExecutor @NonNull Executor executor, Consumer<Boolean> destination) { operation.orTimeout(REQUEST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS) .whenComplete((res, err) -> executor.execute(() -> { long token = Binder.clearCallingIdentity(); try { mCallback.sendResult(result); } finally { Binder.restoreCallingIdentity(token); finish(); } }); } @Override protected void onTimeout(@NonNull RemoteService remoteService) { mCallback.sendResult(null); } @Override public void run() { try { getService().getServiceInterface().onClearRoleHolders(mRoleName, mFlags, mRemoteCallback); } catch (RemoteException e) { Log.e(LOG_TAG, "Error calling onClearRoleHolders()", e); if (err != null) { Log.e(LOG_TAG, "Error calling " + opName + "()", err); destination.accept(false); } else { destination.accept(res != null); } } } /** * Request for {@link #isApplicationQualifiedForRole(String, String, Executor, Consumer)} */ private static final class IsApplicationQualifiedForRoleRequest extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> { @NonNull private final String mRoleName; @NonNull private final String mPackageName; @NonNull private final Executor mExecutor; @NonNull private final Consumer<Boolean> mCallback; @NonNull private final RemoteCallback mRemoteCallback; private IsApplicationQualifiedForRoleRequest(@NonNull RemoteService service, @NonNull String roleName, @NonNull String packageName, @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) { super(service); mRoleName = roleName; mPackageName = packageName; mExecutor = executor; mCallback = callback; mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> { long token = Binder.clearCallingIdentity(); try { boolean qualified = result != null; mCallback.accept(qualified); } finally { Binder.restoreCallingIdentity(token); finish(); } })); } @Override protected void onTimeout(RemoteService remoteService) { mExecutor.execute(() -> mCallback.accept(false)); } @Override public void run() { try { getService().getServiceInterface().isApplicationQualifiedForRole(mRoleName, mPackageName, mRemoteCallback); } catch (RemoteException e) { Log.e(LOG_TAG, "Error calling isApplicationQualifiedForRole()", e); } } } /** * Request for {@link #isRoleVisible(String, Executor, Consumer)} */ private static final class IsRoleVisibleRequest extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> { @NonNull private final String mRoleName; @NonNull private final Executor mExecutor; @NonNull private final Consumer<Boolean> mCallback; @NonNull private final RemoteCallback mRemoteCallback; private IsRoleVisibleRequest(@NonNull RemoteService service, @NonNull String roleName, @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) { super(service); mRoleName = roleName; mExecutor = executor; mCallback = callback; mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> { private void propagateCallback(AndroidFuture<Bundle> operation, String opName, RemoteCallback destination) { operation.orTimeout(REQUEST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS) .whenComplete((res, err) -> { long token = Binder.clearCallingIdentity(); try { boolean visible = result != null; mCallback.accept(visible); if (err != null) { Log.e(LOG_TAG, "Error calling " + opName + "()", err); destination.sendResult(null); } else { destination.sendResult(res); } } finally { Binder.restoreCallingIdentity(token); finish(); } })); } @Override protected void onTimeout(RemoteService remoteService) { mExecutor.execute(() -> mCallback.accept(false)); } @Override public void run() { try { getService().getServiceInterface().isRoleVisible(mRoleName, mRemoteCallback); } catch (RemoteException e) { Log.e(LOG_TAG, "Error calling isRoleVisible()", e); } } }); } } Loading
core/java/android/app/role/RoleControllerManager.java +98 −402 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemService; import android.annotation.UserIdInt; import android.app.ActivityThread; import android.content.ComponentName; import android.content.Context; Loading @@ -29,18 +28,18 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.RemoteCallback; 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; import com.android.internal.infra.AndroidFuture; import com.android.internal.infra.ServiceConnector; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; /** Loading @@ -53,6 +52,8 @@ public class RoleControllerManager { private static final String LOG_TAG = RoleControllerManager.class.getSimpleName(); private static final long REQUEST_TIMEOUT_MILLIS = 15 * 1000; private static volatile ComponentName sRemoteServiceComponentName; private static final Object sRemoteServicesLock = new Object(); Loading @@ -61,10 +62,11 @@ public class RoleControllerManager { * Global remote services (per user) used by all {@link RoleControllerManager managers}. */ @GuardedBy("sRemoteServicesLock") private static final SparseArray<RemoteService> sRemoteServices = new SparseArray<>(); private static final SparseArray<ServiceConnector<IRoleController>> sRemoteServices = new SparseArray<>(); @NonNull private final RemoteService mRemoteService; private final ServiceConnector<IRoleController> mRemoteService; /** * Initialize the remote service component name once so that we can avoid acquiring the Loading Loading @@ -92,10 +94,19 @@ public class RoleControllerManager { @NonNull Handler handler, @NonNull Context context) { synchronized (sRemoteServicesLock) { int userId = context.getUserId(); RemoteService remoteService = sRemoteServices.get(userId); ServiceConnector<IRoleController> remoteService = sRemoteServices.get(userId); if (remoteService == null) { remoteService = new RemoteService(ActivityThread.currentApplication(), remoteServiceComponentName, handler, userId); remoteService = new ServiceConnector.Impl<IRoleController>( ActivityThread.currentApplication(), new Intent(RoleControllerService.SERVICE_INTERFACE) .setComponent(remoteServiceComponentName), 0 /* bindingFlags */, userId, IRoleController.Stub::asInterface) { @Override protected Handler getJobHandler() { return handler; } }; sRemoteServices.put(userId, remoteService); } mRemoteService = remoteService; Loading @@ -120,8 +131,12 @@ public class RoleControllerManager { */ public void grantDefaultRoles(@NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { mRemoteService.scheduleRequest(new GrantDefaultRolesRequest(mRemoteService, executor, callback)); AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> { AndroidFuture<Bundle> future = new AndroidFuture<>(); service.grantDefaultRoles(new RemoteCallback(future::complete)); return future; }); propagateCallback(operation, "grantDefaultRoles", executor, callback); } /** Loading @@ -129,8 +144,13 @@ public class RoleControllerManager { */ public void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { mRemoteService.scheduleRequest(new OnAddRoleHolderRequest(mRemoteService, roleName, packageName, flags, callback)); AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> { AndroidFuture<Bundle> future = new AndroidFuture<>(); service.onAddRoleHolder(roleName, packageName, flags, new RemoteCallback(future::complete)); return future; }); propagateCallback(operation, "onAddRoleHolder", callback); } /** Loading @@ -138,8 +158,13 @@ public class RoleControllerManager { */ public void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { mRemoteService.scheduleRequest(new OnRemoveRoleHolderRequest(mRemoteService, roleName, packageName, flags, callback)); AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> { AndroidFuture<Bundle> future = new AndroidFuture<>(); service.onRemoveRoleHolder(roleName, packageName, flags, new RemoteCallback(future::complete)); return future; }); propagateCallback(operation, "onRemoveRoleHolder", callback); } /** Loading @@ -147,8 +172,13 @@ public class RoleControllerManager { */ public void onClearRoleHolders(@NonNull String roleName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { mRemoteService.scheduleRequest(new OnClearRoleHoldersRequest(mRemoteService, roleName, flags, callback)); AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> { AndroidFuture<Bundle> future = new AndroidFuture<>(); service.onClearRoleHolders(roleName, flags, new RemoteCallback(future::complete)); return future; }); propagateCallback(operation, "onClearRoleHolders", callback); } /** Loading @@ -157,8 +187,13 @@ public class RoleControllerManager { @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) public void isApplicationQualifiedForRole(@NonNull String roleName, @NonNull String packageName, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { mRemoteService.scheduleRequest(new IsApplicationQualifiedForRoleRequest(mRemoteService, roleName, packageName, executor, callback)); AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> { AndroidFuture<Bundle> future = new AndroidFuture<>(); service.isApplicationQualifiedForRole(roleName, packageName, new RemoteCallback(future::complete)); return future; }); propagateCallback(operation, "isApplicationQualifiedForRole", executor, callback); } /** Loading @@ -167,387 +202,48 @@ public class RoleControllerManager { @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) public void isRoleVisible(@NonNull String roleName, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { mRemoteService.scheduleRequest(new IsRoleVisibleRequest(mRemoteService, roleName, executor, callback)); } /** * 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, 0, 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 #grantDefaultRoles(Executor, Consumer)}. */ private static final class GrantDefaultRolesRequest extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> { @NonNull private final Executor mExecutor; @NonNull private final Consumer<Boolean> mCallback; @NonNull private final RemoteCallback mRemoteCallback; private GrantDefaultRolesRequest(@NonNull RemoteService service, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { super(service); mExecutor = executor; mCallback = callback; mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> { long token = Binder.clearCallingIdentity(); try { boolean successful = result != null; mCallback.accept(successful); } finally { Binder.restoreCallingIdentity(token); finish(); } })); } @Override protected void onTimeout(@NonNull RemoteService remoteService) { mExecutor.execute(() -> mCallback.accept(false)); } @Override public void run() { try { getService().getServiceInterface().grantDefaultRoles(mRemoteCallback); } catch (RemoteException e) { Log.e(LOG_TAG, "Error calling grantDefaultRoles()", e); } } @Override protected void onFailed() { mRemoteCallback.sendResult(null); } } /** * Request for {@link #onAddRoleHolder(String, String, int, RemoteCallback)}. */ 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 RemoteCallback mCallback; @NonNull private final RemoteCallback mRemoteCallback; private OnAddRoleHolderRequest(@NonNull RemoteService service, @NonNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { super(service); mRoleName = roleName; mPackageName = packageName; mFlags = flags; mCallback = callback; mRemoteCallback = new RemoteCallback(result -> { long token = Binder.clearCallingIdentity(); try { mCallback.sendResult(result); } finally { Binder.restoreCallingIdentity(token); finish(); } }); } @Override protected void onTimeout(@NonNull RemoteService remoteService) { mCallback.sendResult(null); } @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, RemoteCallback)}. */ 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 RemoteCallback mCallback; @NonNull private final RemoteCallback mRemoteCallback; private OnRemoveRoleHolderRequest(@NonNull RemoteService service, @NonNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { super(service); mRoleName = roleName; mPackageName = packageName; mFlags = flags; mCallback = callback; mRemoteCallback = new RemoteCallback(result -> { long token = Binder.clearCallingIdentity(); try { mCallback.sendResult(result); } finally { Binder.restoreCallingIdentity(token); finish(); } AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> { AndroidFuture<Bundle> future = new AndroidFuture<>(); service.isRoleVisible(roleName, new RemoteCallback(future::complete)); return future; }); propagateCallback(operation, "isRoleVisible", executor, callback); } @Override protected void onTimeout(@NonNull RemoteService remoteService) { mCallback.sendResult(null); } @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, RemoteCallback)}. */ private static final class OnClearRoleHoldersRequest extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> { @NonNull private final String mRoleName; @RoleManager.ManageHoldersFlags private final int mFlags; @NonNull private final RemoteCallback mCallback; @NonNull private final RemoteCallback mRemoteCallback; private OnClearRoleHoldersRequest(@NonNull RemoteService service, @NonNull String roleName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { super(service); mRoleName = roleName; mFlags = flags; mCallback = callback; mRemoteCallback = new RemoteCallback(result -> { private void propagateCallback(AndroidFuture<Bundle> operation, String opName, @CallbackExecutor @NonNull Executor executor, Consumer<Boolean> destination) { operation.orTimeout(REQUEST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS) .whenComplete((res, err) -> executor.execute(() -> { long token = Binder.clearCallingIdentity(); try { mCallback.sendResult(result); } finally { Binder.restoreCallingIdentity(token); finish(); } }); } @Override protected void onTimeout(@NonNull RemoteService remoteService) { mCallback.sendResult(null); } @Override public void run() { try { getService().getServiceInterface().onClearRoleHolders(mRoleName, mFlags, mRemoteCallback); } catch (RemoteException e) { Log.e(LOG_TAG, "Error calling onClearRoleHolders()", e); if (err != null) { Log.e(LOG_TAG, "Error calling " + opName + "()", err); destination.accept(false); } else { destination.accept(res != null); } } } /** * Request for {@link #isApplicationQualifiedForRole(String, String, Executor, Consumer)} */ private static final class IsApplicationQualifiedForRoleRequest extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> { @NonNull private final String mRoleName; @NonNull private final String mPackageName; @NonNull private final Executor mExecutor; @NonNull private final Consumer<Boolean> mCallback; @NonNull private final RemoteCallback mRemoteCallback; private IsApplicationQualifiedForRoleRequest(@NonNull RemoteService service, @NonNull String roleName, @NonNull String packageName, @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) { super(service); mRoleName = roleName; mPackageName = packageName; mExecutor = executor; mCallback = callback; mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> { long token = Binder.clearCallingIdentity(); try { boolean qualified = result != null; mCallback.accept(qualified); } finally { Binder.restoreCallingIdentity(token); finish(); } })); } @Override protected void onTimeout(RemoteService remoteService) { mExecutor.execute(() -> mCallback.accept(false)); } @Override public void run() { try { getService().getServiceInterface().isApplicationQualifiedForRole(mRoleName, mPackageName, mRemoteCallback); } catch (RemoteException e) { Log.e(LOG_TAG, "Error calling isApplicationQualifiedForRole()", e); } } } /** * Request for {@link #isRoleVisible(String, Executor, Consumer)} */ private static final class IsRoleVisibleRequest extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> { @NonNull private final String mRoleName; @NonNull private final Executor mExecutor; @NonNull private final Consumer<Boolean> mCallback; @NonNull private final RemoteCallback mRemoteCallback; private IsRoleVisibleRequest(@NonNull RemoteService service, @NonNull String roleName, @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) { super(service); mRoleName = roleName; mExecutor = executor; mCallback = callback; mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> { private void propagateCallback(AndroidFuture<Bundle> operation, String opName, RemoteCallback destination) { operation.orTimeout(REQUEST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS) .whenComplete((res, err) -> { long token = Binder.clearCallingIdentity(); try { boolean visible = result != null; mCallback.accept(visible); if (err != null) { Log.e(LOG_TAG, "Error calling " + opName + "()", err); destination.sendResult(null); } else { destination.sendResult(res); } } finally { Binder.restoreCallingIdentity(token); finish(); } })); } @Override protected void onTimeout(RemoteService remoteService) { mExecutor.execute(() -> mCallback.accept(false)); } @Override public void run() { try { getService().getServiceInterface().isRoleVisible(mRoleName, mRemoteCallback); } catch (RemoteException e) { Log.e(LOG_TAG, "Error calling isRoleVisible()", e); } } }); } }