1 /* 2 * Copyright (C) 2018 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.FlaggedApi; 22 import android.annotation.IntDef; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.RequiresPermission; 26 import android.annotation.SuppressLint; 27 import android.annotation.SystemApi; 28 import android.annotation.SystemService; 29 import android.annotation.UserHandleAware; 30 import android.annotation.UserIdInt; 31 import android.app.compat.CompatChanges; 32 import android.compat.annotation.ChangeId; 33 import android.compat.annotation.EnabledSince; 34 import android.content.Context; 35 import android.content.Intent; 36 import android.os.Binder; 37 import android.os.Build; 38 import android.os.Process; 39 import android.os.RemoteCallback; 40 import android.os.RemoteException; 41 import android.os.UserHandle; 42 import android.permission.flags.Flags; 43 import android.util.ArrayMap; 44 import android.util.SparseArray; 45 46 import androidx.annotation.RequiresApi; 47 48 import com.android.internal.annotations.GuardedBy; 49 import com.android.internal.util.Preconditions; 50 import com.android.modules.utils.build.SdkLevel; 51 52 import java.lang.annotation.Retention; 53 import java.lang.annotation.RetentionPolicy; 54 import java.util.List; 55 import java.util.Objects; 56 import java.util.concurrent.Executor; 57 import java.util.function.Consumer; 58 59 /** 60 * This class provides information about and manages roles. 61 * <p> 62 * A role is a unique name within the system associated with certain privileges. The list of 63 * available roles might change with a system app update, so apps should not make assumption about 64 * the availability of roles. Instead, they should always query if the role is available using 65 * {@link #isRoleAvailable(String)} before trying to do anything with it. Some predefined role names 66 * are available as constants in this class, and a list of possibly available roles can be found in 67 * the <a href="{@docRoot}reference/androidx/core/role/package-summary.html">AndroidX Role 68 * library</a>. 69 * <p> 70 * There can be multiple applications qualifying for a role, but only a subset of them can become 71 * role holders. To qualify for a role, an application must meet certain requirements, including 72 * defining certain components in its manifest. These requirements can be found in the AndroidX 73 * Libraries. Then the application will need user consent to become a role holder, which can be 74 * requested using {@link android.app.Activity#startActivityForResult(Intent, int)} with the 75 * {@code Intent} obtained from {@link #createRequestRoleIntent(String)}. 76 * <p> 77 * Upon becoming a role holder, the application may be granted certain privileges that are role 78 * specific. When the application loses its role, these privileges will also be revoked. 79 */ 80 @SystemService(Context.ROLE_SERVICE) 81 public final class RoleManager { 82 /** 83 * The name of the assistant app role. 84 * 85 * @see android.service.voice.VoiceInteractionService 86 */ 87 public static final String ROLE_ASSISTANT = "android.app.role.ASSISTANT"; 88 89 /** 90 * The name of the browser role. 91 * 92 * @see Intent#CATEGORY_APP_BROWSER 93 */ 94 public static final String ROLE_BROWSER = "android.app.role.BROWSER"; 95 96 /** 97 * The name of the dialer role. 98 * 99 * @see Intent#ACTION_DIAL 100 * @see android.telecom.InCallService 101 */ 102 public static final String ROLE_DIALER = "android.app.role.DIALER"; 103 104 /** 105 * The name of the SMS role. 106 * 107 * @see Intent#CATEGORY_APP_MESSAGING 108 */ 109 public static final String ROLE_SMS = "android.app.role.SMS"; 110 111 /** 112 * The name of the emergency role 113 */ 114 public static final String ROLE_EMERGENCY = "android.app.role.EMERGENCY"; 115 116 /** 117 * The name of the home role. 118 * 119 * @see Intent#CATEGORY_HOME 120 */ 121 public static final String ROLE_HOME = "android.app.role.HOME"; 122 123 /** 124 * The name of the call redirection role. 125 * <p> 126 * A call redirection app provides a means to re-write the phone number for an outgoing call to 127 * place the call through a call redirection service. 128 * 129 * @see android.telecom.CallRedirectionService 130 */ 131 public static final String ROLE_CALL_REDIRECTION = "android.app.role.CALL_REDIRECTION"; 132 133 /** 134 * The name of the call screening and caller id role. 135 * 136 * @see android.telecom.CallScreeningService 137 */ 138 public static final String ROLE_CALL_SCREENING = "android.app.role.CALL_SCREENING"; 139 140 /** 141 * The name of the notes role. 142 * 143 * @see Intent#ACTION_CREATE_NOTE 144 * @see Intent#EXTRA_USE_STYLUS_MODE 145 */ 146 public static final String ROLE_NOTES = "android.app.role.NOTES"; 147 148 /** 149 * The name of the Wallet role. 150 * 151 * @see android.nfc.cardemulation.CardEmulation 152 */ 153 @FlaggedApi(Flags.FLAG_WALLET_ROLE_ENABLED) 154 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 155 public static final String ROLE_WALLET = "android.app.role.WALLET"; 156 157 /** 158 * The name of the system wellbeing role. 159 * 160 * @hide 161 */ 162 @SystemApi 163 public static final String ROLE_SYSTEM_WELLBEING = "android.app.role.SYSTEM_WELLBEING"; 164 165 /** 166 * The name of the system supervision role. 167 * 168 * @hide 169 */ 170 @SystemApi 171 public static final String ROLE_SYSTEM_SUPERVISION = "android.app.role.SYSTEM_SUPERVISION"; 172 173 /** 174 * The name of the system activity recognizer role. 175 * 176 * @hide 177 */ 178 @SystemApi 179 public static final String ROLE_SYSTEM_ACTIVITY_RECOGNIZER = 180 "android.app.role.SYSTEM_ACTIVITY_RECOGNIZER"; 181 182 /** 183 * The name of the device policy management role. 184 * 185 * @hide 186 */ 187 @SystemApi 188 public static final String ROLE_DEVICE_POLICY_MANAGEMENT = 189 "android.app.role.DEVICE_POLICY_MANAGEMENT"; 190 191 /** 192 * The name of the financed device kiosk role. 193 * 194 * A financed device is a device purchased through a creditor and typically paid back under an 195 * installment plan. 196 * The creditor has the ability to lock a financed device in case of payment default. 197 * 198 * @hide 199 */ 200 @SystemApi 201 public static final String ROLE_FINANCED_DEVICE_KIOSK = 202 "android.app.role.FINANCED_DEVICE_KIOSK"; 203 204 /** 205 * The name of the system call streaming role. 206 * 207 * @hide 208 */ 209 @SystemApi 210 public static final String ROLE_SYSTEM_CALL_STREAMING = 211 "android.app.role.SYSTEM_CALL_STREAMING"; 212 213 /** 214 * @hide 215 */ 216 @IntDef(flag = true, value = { MANAGE_HOLDERS_FLAG_DONT_KILL_APP }) 217 @Retention(RetentionPolicy.SOURCE) 218 public @interface ManageHoldersFlags {} 219 220 /** 221 * Flag parameter for {@link #addRoleHolderAsUser}, {@link #removeRoleHolderAsUser} and 222 * {@link #clearRoleHoldersAsUser} to indicate that apps should not be killed when changing 223 * their role holder status. 224 * 225 * @hide 226 */ 227 @SystemApi 228 public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1; 229 230 /** 231 * For apps targeting Android V and above, several methods are now user-handle-aware, which 232 * means they use the user contained within the context. For apps targeting an SDK version 233 * <em>below</em> this, the user of the calling process will be used. 234 * 235 * @hide 236 */ 237 @ChangeId 238 @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) 239 public static final long ROLE_MANAGER_USER_HANDLE_AWARE = 303742236L; 240 241 /** 242 * The action used to request user approval of a role for an application. 243 * 244 * @hide 245 */ 246 public static final String ACTION_REQUEST_ROLE = "android.app.role.action.REQUEST_ROLE"; 247 248 /** 249 * The permission required to manage records of role holders in {@link RoleManager} directly. 250 * 251 * @hide 252 */ 253 public static final String PERMISSION_MANAGE_ROLES_FROM_CONTROLLER = 254 "com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER"; 255 256 @NonNull 257 private final Context mContext; 258 259 @NonNull 260 private final IRoleManager mService; 261 262 @GuardedBy("mListenersLock") 263 @NonNull 264 private final SparseArray<ArrayMap<OnRoleHoldersChangedListener, 265 OnRoleHoldersChangedListenerDelegate>> mListeners = new SparseArray<>(); 266 @NonNull 267 private final Object mListenersLock = new Object(); 268 269 @GuardedBy("mRoleControllerManagerLock") 270 @Nullable 271 private RoleControllerManager mRoleControllerManager; 272 private final Object mRoleControllerManagerLock = new Object(); 273 274 /** 275 * Create a new instance of this class. 276 * 277 * @param context the {@link Context} 278 * @param service the {@link IRoleManager} service 279 * 280 * @hide 281 */ RoleManager(@onNull Context context, @NonNull IRoleManager service)282 public RoleManager(@NonNull Context context, @NonNull IRoleManager service) { 283 mContext = context; 284 mService = service; 285 } 286 287 /** 288 * Returns an {@code Intent} suitable for passing to 289 * {@link android.app.Activity#startActivityForResult(Intent, int)} which prompts the user to 290 * grant a role to this application. 291 * <p> 292 * If the role is granted, the {@code resultCode} will be 293 * {@link android.app.Activity#RESULT_OK}, otherwise it will be 294 * {@link android.app.Activity#RESULT_CANCELED}. 295 * 296 * @param roleName the name of requested role 297 * 298 * @return the {@code Intent} to prompt user to grant the role 299 */ 300 @NonNull createRequestRoleIntent(@onNull String roleName)301 public Intent createRequestRoleIntent(@NonNull String roleName) { 302 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 303 Intent intent = new Intent(ACTION_REQUEST_ROLE); 304 intent.setPackage(mContext.getPackageManager().getPermissionControllerPackageName()); 305 intent.putExtra(Intent.EXTRA_ROLE_NAME, roleName); 306 return intent; 307 } 308 309 /** 310 * Check whether a role is available in the system. 311 * 312 * @param roleName the name of role to checking for 313 * 314 * @return whether the role is available in the system 315 */ 316 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) isRoleAvailable(@onNull String roleName)317 public boolean isRoleAvailable(@NonNull String roleName) { 318 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 319 UserHandle user = getContextUserIfAppropriate(); 320 try { 321 return mService.isRoleAvailableAsUser(roleName, user.getIdentifier()); 322 } catch (RemoteException e) { 323 throw e.rethrowFromSystemServer(); 324 } 325 } 326 327 /** 328 * Check whether the calling application is holding a particular role. 329 * 330 * @param roleName the name of the role to check for 331 * 332 * @return whether the calling application is holding the role 333 */ 334 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) isRoleHeld(@onNull String roleName)335 public boolean isRoleHeld(@NonNull String roleName) { 336 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 337 UserHandle user = getContextUserIfAppropriate(); 338 try { 339 return mService.isRoleHeldAsUser(roleName, mContext.getPackageName(), 340 user.getIdentifier()); 341 } catch (RemoteException e) { 342 throw e.rethrowFromSystemServer(); 343 } 344 } 345 346 /** 347 * Get package names of the applications holding the role. 348 * <p> 349 * <strong>Note:</strong> Using this API requires holding 350 * {@code android.permission.MANAGE_ROLE_HOLDERS}. 351 * 352 * @param roleName the name of the role to get the role holder for 353 * 354 * @return a list of package names of the role holders, or an empty list if none. 355 * 356 * @see #getRoleHoldersAsUser(String, UserHandle) 357 * 358 * @hide 359 */ 360 @NonNull 361 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 362 @SystemApi 363 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) getRoleHolders(@onNull String roleName)364 public List<String> getRoleHolders(@NonNull String roleName) { 365 return getRoleHoldersAsUser(roleName, getContextUserIfAppropriate()); 366 } 367 368 /** 369 * Get package names of the applications holding the role. 370 * <p> 371 * <strong>Note:</strong> Using this API requires holding 372 * {@code android.permission.MANAGE_ROLE_HOLDERS} and if the user id is not the current user 373 * {@code android.permission.INTERACT_ACROSS_USERS_FULL}. 374 * 375 * @param roleName the name of the role to get the role holder for 376 * @param user the user to get the role holder for 377 * 378 * @return a list of package names of the role holders, or an empty list if none. 379 * 380 * @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer) 381 * @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer) 382 * @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, Consumer) 383 * 384 * @hide 385 */ 386 @NonNull 387 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 388 @SystemApi getRoleHoldersAsUser(@onNull String roleName, @NonNull UserHandle user)389 public List<String> getRoleHoldersAsUser(@NonNull String roleName, @NonNull UserHandle user) { 390 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 391 Objects.requireNonNull(user, "user cannot be null"); 392 try { 393 return mService.getRoleHoldersAsUser(roleName, user.getIdentifier()); 394 } catch (RemoteException e) { 395 throw e.rethrowFromSystemServer(); 396 } 397 } 398 399 /** 400 * Add a specific application to the holders of a role. If the role is exclusive, the previous 401 * holder will be replaced. 402 * <p> 403 * <strong>Note:</strong> Using this API requires holding 404 * {@code android.permission.MANAGE_ROLE_HOLDERS} and if the user id is not the current user 405 * {@code android.permission.INTERACT_ACROSS_USERS_FULL}. 406 * 407 * @param roleName the name of the role to add the role holder for 408 * @param packageName the package name of the application to add to the role holders 409 * @param flags optional behavior flags 410 * @param user the user to add the role holder for 411 * @param executor the {@code Executor} to run the callback on. 412 * @param callback the callback for whether this call is successful 413 * 414 * @see #getRoleHoldersAsUser(String, UserHandle) 415 * @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer) 416 * @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, Consumer) 417 * 418 * @hide 419 */ 420 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 421 @SystemApi addRoleHolderAsUser(@onNull String roleName, @NonNull String packageName, @ManageHoldersFlags int flags, @NonNull UserHandle user, @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback)422 public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName, 423 @ManageHoldersFlags int flags, @NonNull UserHandle user, 424 @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) { 425 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 426 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); 427 Objects.requireNonNull(user, "user cannot be null"); 428 Objects.requireNonNull(executor, "executor cannot be null"); 429 Objects.requireNonNull(callback, "callback cannot be null"); 430 try { 431 mService.addRoleHolderAsUser(roleName, packageName, flags, user.getIdentifier(), 432 createRemoteCallback(executor, callback)); 433 } catch (RemoteException e) { 434 throw e.rethrowFromSystemServer(); 435 } 436 } 437 438 /** 439 * Remove a specific application from the holders of a role. 440 * <p> 441 * <strong>Note:</strong> Using this API requires holding 442 * {@code android.permission.MANAGE_ROLE_HOLDERS} and if the user id is not the current user 443 * {@code android.permission.INTERACT_ACROSS_USERS_FULL}. 444 * 445 * @param roleName the name of the role to remove the role holder for 446 * @param packageName the package name of the application to remove from the role holders 447 * @param flags optional behavior flags 448 * @param user the user to remove the role holder for 449 * @param executor the {@code Executor} to run the callback on. 450 * @param callback the callback for whether this call is successful 451 * 452 * @see #getRoleHoldersAsUser(String, UserHandle) 453 * @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer) 454 * @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, Consumer) 455 * 456 * @hide 457 */ 458 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 459 @SystemApi removeRoleHolderAsUser(@onNull String roleName, @NonNull String packageName, @ManageHoldersFlags int flags, @NonNull UserHandle user, @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback)460 public void removeRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName, 461 @ManageHoldersFlags int flags, @NonNull UserHandle user, 462 @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) { 463 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 464 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); 465 Objects.requireNonNull(user, "user cannot be null"); 466 Objects.requireNonNull(executor, "executor cannot be null"); 467 Objects.requireNonNull(callback, "callback cannot be null"); 468 try { 469 mService.removeRoleHolderAsUser(roleName, packageName, flags, user.getIdentifier(), 470 createRemoteCallback(executor, callback)); 471 } catch (RemoteException e) { 472 throw e.rethrowFromSystemServer(); 473 } 474 } 475 476 /** 477 * Remove all holders of a role. 478 * <p> 479 * <strong>Note:</strong> Using this API requires holding 480 * {@code android.permission.MANAGE_ROLE_HOLDERS} and if the user id is not the current user 481 * {@code android.permission.INTERACT_ACROSS_USERS_FULL}. 482 * 483 * @param roleName the name of the role to remove role holders for 484 * @param flags optional behavior flags 485 * @param user the user to remove role holders for 486 * @param executor the {@code Executor} to run the callback on. 487 * @param callback the callback for whether this call is successful 488 * 489 * @see #getRoleHoldersAsUser(String, UserHandle) 490 * @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer) 491 * @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer) 492 * 493 * @hide 494 */ 495 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 496 @SystemApi clearRoleHoldersAsUser(@onNull String roleName, @ManageHoldersFlags int flags, @NonNull UserHandle user, @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback)497 public void clearRoleHoldersAsUser(@NonNull String roleName, @ManageHoldersFlags int flags, 498 @NonNull UserHandle user, @CallbackExecutor @NonNull Executor executor, 499 @NonNull Consumer<Boolean> callback) { 500 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 501 Objects.requireNonNull(user, "user cannot be null"); 502 Objects.requireNonNull(executor, "executor cannot be null"); 503 Objects.requireNonNull(callback, "callback cannot be null"); 504 try { 505 mService.clearRoleHoldersAsUser(roleName, flags, user.getIdentifier(), 506 createRemoteCallback(executor, callback)); 507 } catch (RemoteException e) { 508 throw e.rethrowFromSystemServer(); 509 } 510 } 511 512 /** 513 * Get package name of the application holding the role for a default application. 514 * <p> 515 * Only roles describing default applications can be used with this method. They can have 516 * at most one holder. 517 * 518 * @param roleName the name of the default application role to get 519 * 520 * @return a package name of the role holder or {@code null} if not set. 521 * 522 * @see #setDefaultApplication(String, String, int, Executor, Consumer) 523 * 524 * @hide 525 */ 526 @Nullable 527 @RequiresPermission(Manifest.permission.MANAGE_DEFAULT_APPLICATIONS) 528 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 529 @UserHandleAware 530 @SystemApi getDefaultApplication(@onNull String roleName)531 public String getDefaultApplication(@NonNull String roleName) { 532 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 533 try { 534 return mService.getDefaultApplicationAsUser( 535 roleName, mContext.getUser().getIdentifier()); 536 } catch (RemoteException e) { 537 throw e.rethrowFromSystemServer(); 538 } 539 } 540 541 /** 542 * Set a specific application as the default application. 543 * <p> 544 * Only roles describing default applications can be used with this method. They can have 545 * at most one holder. 546 * 547 * @param roleName the name of the default application role to set the role holder for 548 * @param packageName the package name of the application to set as the default application, 549 * or {@code null} to unset. 550 * @param flags optional behavior flags 551 * @param executor the {@code Executor} to run the callback on. 552 * @param callback the callback for whether this call is successful 553 * 554 * @see #getDefaultApplication(String) 555 * 556 * @hide 557 */ 558 @RequiresPermission(Manifest.permission.MANAGE_DEFAULT_APPLICATIONS) 559 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 560 @UserHandleAware 561 @SystemApi setDefaultApplication(@onNull String roleName, @Nullable String packageName, @ManageHoldersFlags int flags, @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback)562 public void setDefaultApplication(@NonNull String roleName, @Nullable String packageName, 563 @ManageHoldersFlags int flags, @CallbackExecutor @NonNull Executor executor, 564 @NonNull Consumer<Boolean> callback) { 565 // Prior to Android V some devices might require the "packageName" to be non-null. 566 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 567 Objects.requireNonNull(executor, "executor cannot be null"); 568 Objects.requireNonNull(callback, "callback cannot be null"); 569 try { 570 mService.setDefaultApplicationAsUser(roleName, packageName, flags, 571 mContext.getUser().getIdentifier(), createRemoteCallback(executor, callback)); 572 } catch (RemoteException e) { 573 throw e.rethrowFromSystemServer(); 574 } 575 } 576 577 @NonNull createRemoteCallback(@onNull Executor executor, @NonNull Consumer<Boolean> callback)578 private static RemoteCallback createRemoteCallback(@NonNull Executor executor, 579 @NonNull Consumer<Boolean> callback) { 580 return new RemoteCallback(result -> executor.execute(() -> { 581 boolean successful = result != null; 582 final long token = Binder.clearCallingIdentity(); 583 try { 584 callback.accept(successful); 585 } finally { 586 Binder.restoreCallingIdentity(token); 587 } 588 })); 589 } 590 591 /** 592 * Add a listener to observe role holder changes 593 * <p> 594 * <strong>Note:</strong> Using this API requires holding 595 * {@code android.permission.OBSERVE_ROLE_HOLDERS} and if the user id is not the current user 596 * {@code android.permission.INTERACT_ACROSS_USERS_FULL}. 597 * 598 * @param executor the {@code Executor} to call the listener on. 599 * @param listener the listener to be added 600 * @param user the user to add the listener for 601 * 602 * @see #removeOnRoleHoldersChangedListenerAsUser(OnRoleHoldersChangedListener, UserHandle) 603 * 604 * @hide 605 */ 606 @RequiresPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS) 607 @SuppressLint("SamShouldBeLast") // TODO(b/190240500): remove this 608 @SystemApi addOnRoleHoldersChangedListenerAsUser(@allbackExecutor @onNull Executor executor, @NonNull OnRoleHoldersChangedListener listener, @NonNull UserHandle user)609 public void addOnRoleHoldersChangedListenerAsUser(@CallbackExecutor @NonNull Executor executor, 610 @NonNull OnRoleHoldersChangedListener listener, @NonNull UserHandle user) { 611 Objects.requireNonNull(executor, "executor cannot be null"); 612 Objects.requireNonNull(listener, "listener cannot be null"); 613 Objects.requireNonNull(user, "user cannot be null"); 614 int userId = user.getIdentifier(); 615 synchronized (mListenersLock) { 616 ArrayMap<OnRoleHoldersChangedListener, OnRoleHoldersChangedListenerDelegate> listeners = 617 mListeners.get(userId); 618 if (listeners == null) { 619 listeners = new ArrayMap<>(); 620 mListeners.put(userId, listeners); 621 } else { 622 if (listeners.containsKey(listener)) { 623 return; 624 } 625 } 626 OnRoleHoldersChangedListenerDelegate listenerDelegate = 627 new OnRoleHoldersChangedListenerDelegate(executor, listener); 628 try { 629 mService.addOnRoleHoldersChangedListenerAsUser(listenerDelegate, userId); 630 } catch (RemoteException e) { 631 throw e.rethrowFromSystemServer(); 632 } 633 listeners.put(listener, listenerDelegate); 634 } 635 } 636 637 /** 638 * Remove a listener observing role holder changes 639 * <p> 640 * <strong>Note:</strong> Using this API requires holding 641 * {@code android.permission.OBSERVE_ROLE_HOLDERS} and if the user id is not the current user 642 * {@code android.permission.INTERACT_ACROSS_USERS_FULL}. 643 * 644 * @param listener the listener to be removed 645 * @param user the user to remove the listener for 646 * 647 * @see #addOnRoleHoldersChangedListenerAsUser(Executor, OnRoleHoldersChangedListener, 648 * UserHandle) 649 * 650 * @hide 651 */ 652 @RequiresPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS) 653 @SuppressLint("SamShouldBeLast") // TODO(b/190240500): remove this 654 @SystemApi removeOnRoleHoldersChangedListenerAsUser( @onNull OnRoleHoldersChangedListener listener, @NonNull UserHandle user)655 public void removeOnRoleHoldersChangedListenerAsUser( 656 @NonNull OnRoleHoldersChangedListener listener, @NonNull UserHandle user) { 657 Objects.requireNonNull(listener, "listener cannot be null"); 658 Objects.requireNonNull(user, "user cannot be null"); 659 int userId = user.getIdentifier(); 660 synchronized (mListenersLock) { 661 ArrayMap<OnRoleHoldersChangedListener, OnRoleHoldersChangedListenerDelegate> listeners = 662 mListeners.get(userId); 663 if (listeners == null) { 664 return; 665 } 666 OnRoleHoldersChangedListenerDelegate listenerDelegate = listeners.get(listener); 667 if (listenerDelegate == null) { 668 return; 669 } 670 try { 671 mService.removeOnRoleHoldersChangedListenerAsUser(listenerDelegate, 672 user.getIdentifier()); 673 } catch (RemoteException e) { 674 throw e.rethrowFromSystemServer(); 675 } 676 listeners.remove(listener); 677 if (listeners.isEmpty()) { 678 mListeners.remove(userId); 679 } 680 } 681 } 682 683 /** 684 * Check whether role qualifications should be bypassed. 685 * <p> 686 * Only the shell is allowed to do this, the qualification for the shell role itself cannot be 687 * bypassed, and each role needs to explicitly allow bypassing qualification in its definition. 688 * The bypass state will not be persisted across reboot. 689 * 690 * @return whether role qualification should be bypassed 691 * 692 * @hide 693 */ 694 @RequiresApi(Build.VERSION_CODES.S) 695 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 696 @SystemApi isBypassingRoleQualification()697 public boolean isBypassingRoleQualification() { 698 try { 699 return mService.isBypassingRoleQualification(); 700 } catch (RemoteException e) { 701 throw e.rethrowFromSystemServer(); 702 } 703 } 704 705 /** 706 * Set whether role qualifications should be bypassed. 707 * <p> 708 * Only the shell is allowed to do this, the qualification for the shell role itself cannot be 709 * bypassed, and each role needs to explicitly allow bypassing qualification in its definition. 710 * The bypass state will not be persisted across reboot. 711 * 712 * @param bypassRoleQualification whether role qualification should be bypassed 713 * 714 * @hide 715 */ 716 @RequiresApi(Build.VERSION_CODES.S) 717 @RequiresPermission(Manifest.permission.BYPASS_ROLE_QUALIFICATION) 718 @SystemApi setBypassingRoleQualification(boolean bypassRoleQualification)719 public void setBypassingRoleQualification(boolean bypassRoleQualification) { 720 try { 721 mService.setBypassingRoleQualification(bypassRoleQualification); 722 } catch (RemoteException e) { 723 throw e.rethrowFromSystemServer(); 724 } 725 } 726 727 /** 728 * Check whether role currently enables fallback to default holder. 729 * <p> 730 * This is based on the "None" holder being actively selected, in which case don't fallback. 731 * 732 * @param roleName the name of the role being queried 733 * 734 * @return whether fallback is enabled for the provided role 735 * 736 * @hide 737 */ 738 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 739 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 740 @FlaggedApi(Flags.FLAG_SYSTEM_SERVER_ROLE_CONTROLLER_ENABLED) 741 @UserHandleAware 742 @SystemApi isRoleFallbackEnabled(@onNull String roleName)743 public boolean isRoleFallbackEnabled(@NonNull String roleName) { 744 try { 745 return mService.isRoleFallbackEnabledAsUser(roleName, 746 mContext.getUser().getIdentifier()); 747 } catch (RemoteException e) { 748 throw e.rethrowFromSystemServer(); 749 } 750 } 751 752 /** 753 * Set whether role should fallback to a default role holder. 754 * 755 * @param roleName the name of the role being queried. 756 * @param fallbackEnabled whether to enable fallback holders for this role. 757 * 758 * @hide 759 */ 760 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 761 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 762 @FlaggedApi(Flags.FLAG_SYSTEM_SERVER_ROLE_CONTROLLER_ENABLED) 763 @UserHandleAware 764 @SystemApi setRoleFallbackEnabled(@onNull String roleName, boolean fallbackEnabled)765 public void setRoleFallbackEnabled(@NonNull String roleName, boolean fallbackEnabled) { 766 try { 767 mService.setRoleFallbackEnabledAsUser(roleName, fallbackEnabled, 768 mContext.getUser().getIdentifier()); 769 } catch (RemoteException e) { 770 throw e.rethrowFromSystemServer(); 771 } 772 } 773 774 /** 775 * Set the names of all the available roles. Should only be called from 776 * {@link android.app.role.RoleControllerService}. 777 * <p> 778 * <strong>Note:</strong> Using this API requires holding 779 * {@link #PERMISSION_MANAGE_ROLES_FROM_CONTROLLER}. 780 * 781 * @param roleNames the names of all the available roles 782 * 783 * @deprecated This is only usable by the role controller service, which is an internal 784 * implementation detail inside role. 785 * 786 * @hide 787 */ 788 @Deprecated 789 @RequiresPermission(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER) 790 @SystemApi 791 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) setRoleNamesFromController(@onNull List<String> roleNames)792 public void setRoleNamesFromController(@NonNull List<String> roleNames) { 793 Objects.requireNonNull(roleNames, "roleNames cannot be null"); 794 UserHandle user = getContextUserIfAppropriate(); 795 try { 796 mService.setRoleNamesFromControllerAsUser(roleNames, user.getIdentifier()); 797 } catch (RemoteException e) { 798 throw e.rethrowFromSystemServer(); 799 } 800 } 801 802 /** 803 * Add a specific application to the holders of a role, only modifying records inside 804 * {@link RoleManager}. Should only be called from 805 * {@link android.app.role.RoleControllerService}. 806 * <p> 807 * <strong>Note:</strong> Using this API requires holding 808 * {@link #PERMISSION_MANAGE_ROLES_FROM_CONTROLLER}. 809 * 810 * @param roleName the name of the role to add the role holder for 811 * @param packageName the package name of the application to add to the role holders 812 * 813 * @return whether the operation was successful, and will also be {@code true} if a matching 814 * role holder is already found. 815 * 816 * @see #getRoleHolders(String) 817 * @see #removeRoleHolderFromController(String, String) 818 * 819 * @deprecated This is only usable by the role controller service, which is an internal 820 * implementation detail inside role. 821 * 822 * @hide 823 */ 824 @Deprecated 825 @RequiresPermission(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER) 826 @SystemApi 827 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) addRoleHolderFromController(@onNull String roleName, @NonNull String packageName)828 public boolean addRoleHolderFromController(@NonNull String roleName, 829 @NonNull String packageName) { 830 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 831 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); 832 UserHandle user = getContextUserIfAppropriate(); 833 try { 834 return mService.addRoleHolderFromControllerAsUser(roleName, packageName, 835 user.getIdentifier()); 836 } catch (RemoteException e) { 837 throw e.rethrowFromSystemServer(); 838 } 839 } 840 841 /** 842 * Remove a specific application from the holders of a role, only modifying records inside 843 * {@link RoleManager}. Should only be called from 844 * {@link android.app.role.RoleControllerService}. 845 * <p> 846 * <strong>Note:</strong> Using this API requires holding 847 * {@link #PERMISSION_MANAGE_ROLES_FROM_CONTROLLER}. 848 * 849 * @param roleName the name of the role to remove the role holder for 850 * @param packageName the package name of the application to remove from the role holders 851 * 852 * @return whether the operation was successful, and will also be {@code true} if no matching 853 * role holder was found to remove. 854 * 855 * @see #getRoleHolders(String) 856 * @see #addRoleHolderFromController(String, String) 857 * 858 * @deprecated This is only usable by the role controller service, which is an internal 859 * implementation detail inside role. 860 * 861 * @hide 862 */ 863 @Deprecated 864 @RequiresPermission(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER) 865 @SystemApi 866 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) removeRoleHolderFromController(@onNull String roleName, @NonNull String packageName)867 public boolean removeRoleHolderFromController(@NonNull String roleName, 868 @NonNull String packageName) { 869 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 870 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); 871 UserHandle user = getContextUserIfAppropriate(); 872 try { 873 return mService.removeRoleHolderFromControllerAsUser(roleName, packageName, 874 user.getIdentifier()); 875 } catch (RemoteException e) { 876 throw e.rethrowFromSystemServer(); 877 } 878 } 879 880 /** 881 * Returns the list of all roles that the given package is currently holding 882 * 883 * @param packageName the package name 884 * @return the list of role names 885 * 886 * @deprecated This is only usable by the role controller service, which is an internal 887 * implementation detail inside role. 888 * 889 * @hide 890 */ 891 @Deprecated 892 @NonNull 893 @RequiresPermission(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER) 894 @SystemApi 895 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) getHeldRolesFromController(@onNull String packageName)896 public List<String> getHeldRolesFromController(@NonNull String packageName) { 897 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); 898 UserHandle user = getContextUserIfAppropriate(); 899 try { 900 return mService.getHeldRolesFromControllerAsUser(packageName, user.getIdentifier()); 901 } catch (RemoteException e) { 902 throw e.rethrowFromSystemServer(); 903 } 904 } 905 getContextUserIfAppropriate()906 private UserHandle getContextUserIfAppropriate() { 907 return CompatChanges.isChangeEnabled(ROLE_MANAGER_USER_HANDLE_AWARE) ? mContext.getUser() 908 : Process.myUserHandle(); 909 } 910 911 /** 912 * Get the role holder of {@link #ROLE_BROWSER} without requiring 913 * {@link Manifest.permission#OBSERVE_ROLE_HOLDERS}, as in 914 * {@link android.content.pm.PackageManager#getDefaultBrowserPackageNameAsUser(int)} 915 * 916 * @param userId the user ID 917 * @return the package name of the default browser, or {@code null} if none 918 * 919 * @hide 920 */ 921 @RequiresApi(Build.VERSION_CODES.S) 922 @Nullable 923 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) getBrowserRoleHolder(@serIdInt int userId)924 public String getBrowserRoleHolder(@UserIdInt int userId) { 925 try { 926 return mService.getBrowserRoleHolder(userId); 927 } catch (RemoteException e) { 928 throw e.rethrowFromSystemServer(); 929 } 930 } 931 932 /** 933 * Set the role holder of {@link #ROLE_BROWSER} requiring 934 * {@link Manifest.permission.SET_PREFERRED_APPLICATIONS} instead of 935 * {@link Manifest.permission#MANAGE_ROLE_HOLDERS}, as in 936 * {@link android.content.pm.PackageManager#setDefaultBrowserPackageNameAsUser(String, int)} 937 * 938 * @param packageName the package name of the default browser, or {@code null} if none 939 * @param userId the user ID 940 * @return whether the default browser was set successfully 941 * 942 * @hide 943 */ 944 @RequiresApi(Build.VERSION_CODES.S) 945 @Nullable 946 @RequiresPermission(Manifest.permission.SET_PREFERRED_APPLICATIONS) 947 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) setBrowserRoleHolder(@ullable String packageName, @UserIdInt int userId)948 public boolean setBrowserRoleHolder(@Nullable String packageName, @UserIdInt int userId) { 949 try { 950 return mService.setBrowserRoleHolder(packageName, userId); 951 } catch (RemoteException e) { 952 throw e.rethrowFromSystemServer(); 953 } 954 } 955 956 /** 957 * Allows getting the role holder for {@link #ROLE_SMS} without requiring 958 * {@link Manifest.permission#OBSERVE_ROLE_HOLDERS}, as in 959 * {@link android.provider.Telephony.Sms#getDefaultSmsPackage(Context)}. 960 * 961 * @param userId the user ID to get the default SMS package for 962 * @return the package name of the default SMS app, or {@code null} if none 963 * 964 * @hide 965 */ 966 @RequiresApi(Build.VERSION_CODES.S) 967 @Nullable 968 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) getSmsRoleHolder(@serIdInt int userId)969 public String getSmsRoleHolder(@UserIdInt int userId) { 970 try { 971 return mService.getSmsRoleHolder(userId); 972 } catch (RemoteException e) { 973 throw e.rethrowFromSystemServer(); 974 } 975 } 976 977 /** 978 * Allows getting the role holder for {@link #ROLE_EMERGENCY} without requiring 979 * {@link Manifest.permission#OBSERVE_ROLE_HOLDERS}. 980 * 981 * @param userId the user ID to get the default emergency package for 982 * @return the package name of the default emergency app, or {@code null} if none 983 * 984 * @hide 985 */ 986 @FlaggedApi(Flags.FLAG_GET_EMERGENCY_ROLE_HOLDER_API_ENABLED) 987 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 988 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) 989 @Nullable 990 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) getEmergencyRoleHolder(@serIdInt int userId)991 public String getEmergencyRoleHolder(@UserIdInt int userId) { 992 try { 993 return mService.getEmergencyRoleHolder(userId); 994 } catch (RemoteException e) { 995 throw e.rethrowFromSystemServer(); 996 } 997 } 998 999 /** 1000 * Check whether a role should be visible to user. 1001 * 1002 * @param roleName name of the role to check for 1003 * @param executor the executor to execute callback on 1004 * @param callback the callback to receive whether the role should be visible to user 1005 * 1006 * @hide 1007 */ 1008 @RequiresApi(Build.VERSION_CODES.S) 1009 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 1010 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) 1011 @SystemApi isRoleVisible(@onNull String roleName, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback)1012 public void isRoleVisible(@NonNull String roleName, 1013 @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { 1014 if (SdkLevel.isAtLeastV() && Flags.systemServerRoleControllerEnabled()) { 1015 int userId = getContextUserIfAppropriate().getIdentifier(); 1016 boolean visible; 1017 try { 1018 visible = mService.isRoleVisibleAsUser(roleName, userId); 1019 } catch (RemoteException e) { 1020 throw e.rethrowFromSystemServer(); 1021 } 1022 executor.execute(() -> { 1023 final long token = Binder.clearCallingIdentity(); 1024 try { 1025 callback.accept(visible); 1026 } finally { 1027 Binder.restoreCallingIdentity(token); 1028 } 1029 }); 1030 } else { 1031 getRoleControllerManager().isRoleVisible(roleName, executor, callback); 1032 } 1033 } 1034 1035 /** 1036 * Check whether an application is visible for a role. 1037 * 1038 * While an application can be qualified for a role, it can still stay hidden from user (thus 1039 * not visible). If an application is visible for a role, we may show things related to the role 1040 * for it, e.g. showing an entry pointing to the role settings in its application info page. 1041 * 1042 * @param roleName the name of the role to check for 1043 * @param packageName the package name of the application to check for 1044 * @param executor the executor to execute callback on 1045 * @param callback the callback to receive whether the application is visible for the role 1046 * 1047 * @hide 1048 */ 1049 @RequiresApi(Build.VERSION_CODES.S) 1050 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 1051 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) 1052 @SystemApi isApplicationVisibleForRole(@onNull String roleName, @NonNull String packageName, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback)1053 public void isApplicationVisibleForRole(@NonNull String roleName, @NonNull String packageName, 1054 @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { 1055 if (SdkLevel.isAtLeastV() && Flags.systemServerRoleControllerEnabled()) { 1056 int userId = getContextUserIfAppropriate().getIdentifier(); 1057 boolean visible; 1058 try { 1059 visible = mService.isApplicationVisibleForRoleAsUser(roleName, packageName, userId); 1060 } catch (RemoteException e) { 1061 throw e.rethrowFromSystemServer(); 1062 } 1063 executor.execute(() -> { 1064 final long token = Binder.clearCallingIdentity(); 1065 try { 1066 callback.accept(visible); 1067 } finally { 1068 Binder.restoreCallingIdentity(token); 1069 } 1070 }); 1071 } else { 1072 getRoleControllerManager().isApplicationVisibleForRole(roleName, packageName, executor, 1073 callback); 1074 } 1075 } 1076 1077 @NonNull getRoleControllerManager()1078 private RoleControllerManager getRoleControllerManager() { 1079 synchronized (mRoleControllerManagerLock) { 1080 if (mRoleControllerManager == null) { 1081 mRoleControllerManager = new RoleControllerManager(mContext); 1082 } 1083 return mRoleControllerManager; 1084 } 1085 } 1086 1087 private static class OnRoleHoldersChangedListenerDelegate 1088 extends IOnRoleHoldersChangedListener.Stub { 1089 1090 @NonNull 1091 private final Executor mExecutor; 1092 @NonNull 1093 private final OnRoleHoldersChangedListener mListener; 1094 OnRoleHoldersChangedListenerDelegate(@onNull Executor executor, @NonNull OnRoleHoldersChangedListener listener)1095 OnRoleHoldersChangedListenerDelegate(@NonNull Executor executor, 1096 @NonNull OnRoleHoldersChangedListener listener) { 1097 mExecutor = executor; 1098 mListener = listener; 1099 } 1100 1101 @Override onRoleHoldersChanged(@onNull String roleName, @UserIdInt int userId)1102 public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) { 1103 final long token = Binder.clearCallingIdentity(); 1104 try { 1105 mExecutor.execute(() -> 1106 mListener.onRoleHoldersChanged(roleName, UserHandle.of(userId))); 1107 } finally { 1108 Binder.restoreCallingIdentity(token); 1109 } 1110 } 1111 } 1112 } 1113