1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.app.role; 18 19 import android.Manifest; 20 import android.annotation.CallbackExecutor; 21 import android.annotation.NonNull; 22 import android.annotation.RequiresPermission; 23 import android.annotation.SystemService; 24 import android.annotation.UserIdInt; 25 import android.app.ActivityThread; 26 import android.content.ComponentName; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.pm.PackageManager; 30 import android.content.pm.ResolveInfo; 31 import android.os.Binder; 32 import android.os.Handler; 33 import android.os.IBinder; 34 import android.os.RemoteCallback; 35 import android.os.RemoteException; 36 import android.util.Log; 37 import android.util.SparseArray; 38 39 import com.android.internal.annotations.GuardedBy; 40 import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService; 41 import com.android.internal.infra.AbstractRemoteService; 42 43 import java.util.concurrent.Executor; 44 import java.util.function.Consumer; 45 46 /** 47 * Interface for communicating with the role controller. 48 * 49 * @hide 50 */ 51 @SystemService(Context.ROLE_CONTROLLER_SERVICE) 52 public class RoleControllerManager { 53 54 private static final String LOG_TAG = RoleControllerManager.class.getSimpleName(); 55 56 private static volatile ComponentName sRemoteServiceComponentName; 57 58 private static final Object sRemoteServicesLock = new Object(); 59 60 /** 61 * Global remote services (per user) used by all {@link RoleControllerManager managers}. 62 */ 63 @GuardedBy("sRemoteServicesLock") 64 private static final SparseArray<RemoteService> sRemoteServices = new SparseArray<>(); 65 66 @NonNull 67 private final RemoteService mRemoteService; 68 69 /** 70 * Initialize the remote service component name once so that we can avoid acquiring the 71 * PackageManagerService lock in constructor. 72 * 73 * @see #createWithInitializedRemoteServiceComponentName(Handler, Context) 74 */ initializeRemoteServiceComponentName(@onNull Context context)75 public static void initializeRemoteServiceComponentName(@NonNull Context context) { 76 sRemoteServiceComponentName = getRemoteServiceComponentName(context); 77 } 78 79 /** 80 * Create a {@link RoleControllerManager} instance with the initialized remote service component 81 * name so that we can avoid acquiring the PackageManagerService lock in constructor. 82 * 83 * @see #initializeRemoteServiceComponentName(Context) 84 */ 85 @NonNull createWithInitializedRemoteServiceComponentName( @onNull Handler handler, @NonNull Context context)86 public static RoleControllerManager createWithInitializedRemoteServiceComponentName( 87 @NonNull Handler handler, @NonNull Context context) { 88 return new RoleControllerManager(sRemoteServiceComponentName, handler, context); 89 } 90 RoleControllerManager(@onNull ComponentName remoteServiceComponentName, @NonNull Handler handler, @NonNull Context context)91 private RoleControllerManager(@NonNull ComponentName remoteServiceComponentName, 92 @NonNull Handler handler, @NonNull Context context) { 93 synchronized (sRemoteServicesLock) { 94 int userId = context.getUserId(); 95 RemoteService remoteService = sRemoteServices.get(userId); 96 if (remoteService == null) { 97 remoteService = new RemoteService(ActivityThread.currentApplication(), 98 remoteServiceComponentName, handler, userId); 99 sRemoteServices.put(userId, remoteService); 100 } 101 mRemoteService = remoteService; 102 } 103 } 104 RoleControllerManager(@onNull Context context)105 public RoleControllerManager(@NonNull Context context) { 106 this(getRemoteServiceComponentName(context), context.getMainThreadHandler(), context); 107 } 108 109 @NonNull getRemoteServiceComponentName(@onNull Context context)110 private static ComponentName getRemoteServiceComponentName(@NonNull Context context) { 111 Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE); 112 PackageManager packageManager = context.getPackageManager(); 113 intent.setPackage(packageManager.getPermissionControllerPackageName()); 114 ResolveInfo resolveInfo = packageManager.resolveService(intent, 0); 115 return resolveInfo.getComponentInfo().getComponentName(); 116 } 117 118 /** 119 * @see RoleControllerService#onGrantDefaultRoles() 120 */ grantDefaultRoles(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Boolean> callback)121 public void grantDefaultRoles(@NonNull @CallbackExecutor Executor executor, 122 @NonNull Consumer<Boolean> callback) { 123 mRemoteService.scheduleRequest(new GrantDefaultRolesRequest(mRemoteService, executor, 124 callback)); 125 } 126 127 /** 128 * @see RoleControllerService#onAddRoleHolder(String, String, int) 129 */ onAddRoleHolder(@onNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback)130 public void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName, 131 @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { 132 mRemoteService.scheduleRequest(new OnAddRoleHolderRequest(mRemoteService, roleName, 133 packageName, flags, callback)); 134 } 135 136 /** 137 * @see RoleControllerService#onRemoveRoleHolder(String, String, int) 138 */ onRemoveRoleHolder(@onNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback)139 public void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName, 140 @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { 141 mRemoteService.scheduleRequest(new OnRemoveRoleHolderRequest(mRemoteService, roleName, 142 packageName, flags, callback)); 143 } 144 145 /** 146 * @see RoleControllerService#onClearRoleHolders(String, int) 147 */ onClearRoleHolders(@onNull String roleName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback)148 public void onClearRoleHolders(@NonNull String roleName, 149 @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { 150 mRemoteService.scheduleRequest(new OnClearRoleHoldersRequest(mRemoteService, roleName, 151 flags, callback)); 152 } 153 154 /** 155 * @see RoleControllerService#onIsApplicationQualifiedForRole(String, String) 156 */ 157 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) isApplicationQualifiedForRole(@onNull String roleName, @NonNull String packageName, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback)158 public void isApplicationQualifiedForRole(@NonNull String roleName, @NonNull String packageName, 159 @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { 160 mRemoteService.scheduleRequest(new IsApplicationQualifiedForRoleRequest(mRemoteService, 161 roleName, packageName, executor, callback)); 162 } 163 164 /** 165 * @see RoleControllerService#onIsRoleVisible(String) 166 */ 167 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) isRoleVisible(@onNull String roleName, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback)168 public void isRoleVisible(@NonNull String roleName, 169 @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { 170 mRemoteService.scheduleRequest(new IsRoleVisibleRequest(mRemoteService, roleName, executor, 171 callback)); 172 } 173 174 /** 175 * Connection to the remote service. 176 */ 177 private static final class RemoteService extends AbstractMultiplePendingRequestsRemoteService< 178 RemoteService, IRoleController> { 179 180 private static final long UNBIND_DELAY_MILLIS = 15 * 1000; 181 private static final long REQUEST_TIMEOUT_MILLIS = 15 * 1000; 182 183 /** 184 * Create a connection to the remote service 185 * 186 * @param context the context to use 187 * @param componentName the component of the service to connect to 188 * @param handler the handler for binding service and callbacks 189 * @param userId the user whom remote service should be connected as 190 */ RemoteService(@onNull Context context, @NonNull ComponentName componentName, @NonNull Handler handler, @UserIdInt int userId)191 RemoteService(@NonNull Context context, @NonNull ComponentName componentName, 192 @NonNull Handler handler, @UserIdInt int userId) { 193 super(context, RoleControllerService.SERVICE_INTERFACE, componentName, userId, 194 service -> Log.e(LOG_TAG, "RemoteService " + service + " died"), handler, 0, 195 false, 1); 196 } 197 198 /** 199 * @return The default handler used by this service. 200 */ 201 @NonNull getHandler()202 public Handler getHandler() { 203 return mHandler; 204 } 205 206 @Override getServiceInterface(@onNull IBinder binder)207 protected @NonNull IRoleController getServiceInterface(@NonNull IBinder binder) { 208 return IRoleController.Stub.asInterface(binder); 209 } 210 211 @Override getTimeoutIdleBindMillis()212 protected long getTimeoutIdleBindMillis() { 213 return UNBIND_DELAY_MILLIS; 214 } 215 216 @Override getRemoteRequestMillis()217 protected long getRemoteRequestMillis() { 218 return REQUEST_TIMEOUT_MILLIS; 219 } 220 221 @Override scheduleRequest( @onNull BasePendingRequest<RemoteService, IRoleController> pendingRequest)222 public void scheduleRequest( 223 @NonNull BasePendingRequest<RemoteService, IRoleController> pendingRequest) { 224 super.scheduleRequest(pendingRequest); 225 } 226 227 @Override scheduleAsyncRequest(@onNull AsyncRequest<IRoleController> request)228 public void scheduleAsyncRequest(@NonNull AsyncRequest<IRoleController> request) { 229 super.scheduleAsyncRequest(request); 230 } 231 } 232 233 /** 234 * Request for {@link #grantDefaultRoles(Executor, Consumer)}. 235 */ 236 private static final class GrantDefaultRolesRequest 237 extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> { 238 239 @NonNull 240 private final Executor mExecutor; 241 @NonNull 242 private final Consumer<Boolean> mCallback; 243 244 @NonNull 245 private final RemoteCallback mRemoteCallback; 246 GrantDefaultRolesRequest(@onNull RemoteService service, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback)247 private GrantDefaultRolesRequest(@NonNull RemoteService service, 248 @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { 249 super(service); 250 251 mExecutor = executor; 252 mCallback = callback; 253 254 mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> { 255 long token = Binder.clearCallingIdentity(); 256 try { 257 boolean successful = result != null; 258 mCallback.accept(successful); 259 } finally { 260 Binder.restoreCallingIdentity(token); 261 finish(); 262 } 263 })); 264 } 265 266 @Override onTimeout(@onNull RemoteService remoteService)267 protected void onTimeout(@NonNull RemoteService remoteService) { 268 mExecutor.execute(() -> mCallback.accept(false)); 269 } 270 271 @Override run()272 public void run() { 273 try { 274 getService().getServiceInterface().grantDefaultRoles(mRemoteCallback); 275 } catch (RemoteException e) { 276 Log.e(LOG_TAG, "Error calling grantDefaultRoles()", e); 277 } 278 } 279 280 @Override onFailed()281 protected void onFailed() { 282 mRemoteCallback.sendResult(null); 283 } 284 } 285 286 /** 287 * Request for {@link #onAddRoleHolder(String, String, int, RemoteCallback)}. 288 */ 289 private static final class OnAddRoleHolderRequest 290 extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> { 291 292 @NonNull 293 private final String mRoleName; 294 @NonNull 295 private final String mPackageName; 296 @RoleManager.ManageHoldersFlags 297 private final int mFlags; 298 @NonNull 299 private final RemoteCallback mCallback; 300 301 @NonNull 302 private final RemoteCallback mRemoteCallback; 303 OnAddRoleHolderRequest(@onNull RemoteService service, @NonNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback)304 private OnAddRoleHolderRequest(@NonNull RemoteService service, @NonNull String roleName, 305 @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, 306 @NonNull RemoteCallback callback) { 307 super(service); 308 309 mRoleName = roleName; 310 mPackageName = packageName; 311 mFlags = flags; 312 mCallback = callback; 313 314 mRemoteCallback = new RemoteCallback(result -> { 315 long token = Binder.clearCallingIdentity(); 316 try { 317 mCallback.sendResult(result); 318 } finally { 319 Binder.restoreCallingIdentity(token); 320 finish(); 321 } 322 }); 323 } 324 325 @Override onTimeout(@onNull RemoteService remoteService)326 protected void onTimeout(@NonNull RemoteService remoteService) { 327 mCallback.sendResult(null); 328 } 329 330 @Override run()331 public void run() { 332 try { 333 getService().getServiceInterface().onAddRoleHolder(mRoleName, mPackageName, mFlags, 334 mRemoteCallback); 335 } catch (RemoteException e) { 336 Log.e(LOG_TAG, "Error calling onAddRoleHolder()", e); 337 } 338 } 339 } 340 341 /** 342 * Request for {@link #onRemoveRoleHolder(String, String, int, RemoteCallback)}. 343 */ 344 private static final class OnRemoveRoleHolderRequest 345 extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> { 346 347 @NonNull 348 private final String mRoleName; 349 @NonNull 350 private final String mPackageName; 351 @RoleManager.ManageHoldersFlags 352 private final int mFlags; 353 @NonNull 354 private final RemoteCallback mCallback; 355 356 @NonNull 357 private final RemoteCallback mRemoteCallback; 358 OnRemoveRoleHolderRequest(@onNull RemoteService service, @NonNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback)359 private OnRemoveRoleHolderRequest(@NonNull RemoteService service, @NonNull String roleName, 360 @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, 361 @NonNull RemoteCallback callback) { 362 super(service); 363 364 mRoleName = roleName; 365 mPackageName = packageName; 366 mFlags = flags; 367 mCallback = callback; 368 369 mRemoteCallback = new RemoteCallback(result -> { 370 long token = Binder.clearCallingIdentity(); 371 try { 372 mCallback.sendResult(result); 373 } finally { 374 Binder.restoreCallingIdentity(token); 375 finish(); 376 } 377 }); 378 } 379 380 @Override onTimeout(@onNull RemoteService remoteService)381 protected void onTimeout(@NonNull RemoteService remoteService) { 382 mCallback.sendResult(null); 383 } 384 385 @Override run()386 public void run() { 387 try { 388 getService().getServiceInterface().onRemoveRoleHolder(mRoleName, mPackageName, 389 mFlags, mRemoteCallback); 390 } catch (RemoteException e) { 391 Log.e(LOG_TAG, "Error calling onRemoveRoleHolder()", e); 392 } 393 } 394 } 395 396 /** 397 * Request for {@link #onClearRoleHolders(String, int, RemoteCallback)}. 398 */ 399 private static final class OnClearRoleHoldersRequest 400 extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> { 401 402 @NonNull 403 private final String mRoleName; 404 @RoleManager.ManageHoldersFlags 405 private final int mFlags; 406 @NonNull 407 private final RemoteCallback mCallback; 408 409 @NonNull 410 private final RemoteCallback mRemoteCallback; 411 OnClearRoleHoldersRequest(@onNull RemoteService service, @NonNull String roleName, @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback)412 private OnClearRoleHoldersRequest(@NonNull RemoteService service, @NonNull String roleName, 413 @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { 414 super(service); 415 416 mRoleName = roleName; 417 mFlags = flags; 418 mCallback = callback; 419 420 mRemoteCallback = new RemoteCallback(result -> { 421 long token = Binder.clearCallingIdentity(); 422 try { 423 mCallback.sendResult(result); 424 } finally { 425 Binder.restoreCallingIdentity(token); 426 finish(); 427 } 428 }); 429 } 430 431 @Override onTimeout(@onNull RemoteService remoteService)432 protected void onTimeout(@NonNull RemoteService remoteService) { 433 mCallback.sendResult(null); 434 } 435 436 @Override run()437 public void run() { 438 try { 439 getService().getServiceInterface().onClearRoleHolders(mRoleName, mFlags, 440 mRemoteCallback); 441 } catch (RemoteException e) { 442 Log.e(LOG_TAG, "Error calling onClearRoleHolders()", e); 443 } 444 } 445 } 446 447 /** 448 * Request for {@link #isApplicationQualifiedForRole(String, String, Executor, Consumer)} 449 */ 450 private static final class IsApplicationQualifiedForRoleRequest extends 451 AbstractRemoteService.PendingRequest<RemoteService, IRoleController> { 452 453 @NonNull 454 private final String mRoleName; 455 @NonNull 456 private final String mPackageName; 457 @NonNull 458 private final Executor mExecutor; 459 @NonNull 460 private final Consumer<Boolean> mCallback; 461 462 @NonNull 463 private final RemoteCallback mRemoteCallback; 464 IsApplicationQualifiedForRoleRequest(@onNull RemoteService service, @NonNull String roleName, @NonNull String packageName, @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback)465 private IsApplicationQualifiedForRoleRequest(@NonNull RemoteService service, 466 @NonNull String roleName, @NonNull String packageName, 467 @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) { 468 super(service); 469 470 mRoleName = roleName; 471 mPackageName = packageName; 472 mExecutor = executor; 473 mCallback = callback; 474 475 mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> { 476 long token = Binder.clearCallingIdentity(); 477 try { 478 boolean qualified = result != null; 479 mCallback.accept(qualified); 480 } finally { 481 Binder.restoreCallingIdentity(token); 482 finish(); 483 } 484 })); 485 } 486 487 @Override onTimeout(RemoteService remoteService)488 protected void onTimeout(RemoteService remoteService) { 489 mExecutor.execute(() -> mCallback.accept(false)); 490 } 491 492 @Override run()493 public void run() { 494 try { 495 getService().getServiceInterface().isApplicationQualifiedForRole(mRoleName, 496 mPackageName, mRemoteCallback); 497 } catch (RemoteException e) { 498 Log.e(LOG_TAG, "Error calling isApplicationQualifiedForRole()", e); 499 } 500 } 501 } 502 503 /** 504 * Request for {@link #isRoleVisible(String, Executor, Consumer)} 505 */ 506 private static final class IsRoleVisibleRequest 507 extends AbstractRemoteService.PendingRequest<RemoteService, IRoleController> { 508 509 @NonNull 510 private final String mRoleName; 511 @NonNull 512 private final Executor mExecutor; 513 @NonNull 514 private final Consumer<Boolean> mCallback; 515 516 @NonNull 517 private final RemoteCallback mRemoteCallback; 518 IsRoleVisibleRequest(@onNull RemoteService service, @NonNull String roleName, @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback)519 private IsRoleVisibleRequest(@NonNull RemoteService service, @NonNull String roleName, 520 @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) { 521 super(service); 522 523 mRoleName = roleName; 524 mExecutor = executor; 525 mCallback = callback; 526 527 mRemoteCallback = new RemoteCallback(result -> mExecutor.execute(() -> { 528 long token = Binder.clearCallingIdentity(); 529 try { 530 boolean visible = result != null; 531 mCallback.accept(visible); 532 } finally { 533 Binder.restoreCallingIdentity(token); 534 finish(); 535 } 536 })); 537 } 538 539 @Override onTimeout(RemoteService remoteService)540 protected void onTimeout(RemoteService remoteService) { 541 mExecutor.execute(() -> mCallback.accept(false)); 542 } 543 544 @Override run()545 public void run() { 546 try { 547 getService().getServiceInterface().isRoleVisible(mRoleName, mRemoteCallback); 548 } catch (RemoteException e) { 549 Log.e(LOG_TAG, "Error calling isRoleVisible()", e); 550 } 551 } 552 } 553 } 554