1 /* 2 * Copyright (C) 2016 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.permission; 18 19 import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED; 20 import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED; 21 import static android.permission.PermissionControllerManager.COUNT_ONLY_WHEN_GRANTED; 22 import static android.permission.PermissionControllerManager.COUNT_WHEN_SYSTEM; 23 24 import static com.android.internal.util.Preconditions.checkArgument; 25 import static com.android.internal.util.Preconditions.checkArgumentNonnegative; 26 import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull; 27 import static com.android.internal.util.Preconditions.checkFlagsArgument; 28 import static com.android.internal.util.Preconditions.checkNotNull; 29 import static com.android.internal.util.Preconditions.checkStringNotEmpty; 30 31 import android.Manifest; 32 import android.annotation.BinderThread; 33 import android.annotation.NonNull; 34 import android.annotation.RequiresPermission; 35 import android.annotation.SystemApi; 36 import android.app.Service; 37 import android.app.admin.DevicePolicyManager.PermissionGrantState; 38 import android.compat.annotation.ChangeId; 39 import android.compat.annotation.Disabled; 40 import android.content.Intent; 41 import android.content.pm.PackageInfo; 42 import android.content.pm.PackageManager; 43 import android.os.Bundle; 44 import android.os.IBinder; 45 import android.os.ParcelFileDescriptor; 46 import android.os.UserHandle; 47 import android.permission.PermissionControllerManager.CountPermissionAppsFlag; 48 import android.util.ArrayMap; 49 import android.util.Log; 50 51 import com.android.internal.infra.AndroidFuture; 52 import com.android.internal.util.CollectionUtils; 53 import com.android.internal.util.Preconditions; 54 55 import java.io.FileDescriptor; 56 import java.io.IOException; 57 import java.io.InputStream; 58 import java.io.OutputStream; 59 import java.io.PrintWriter; 60 import java.util.ArrayList; 61 import java.util.Arrays; 62 import java.util.List; 63 import java.util.Map; 64 import java.util.Objects; 65 import java.util.concurrent.CountDownLatch; 66 import java.util.concurrent.Executor; 67 import java.util.function.Consumer; 68 import java.util.function.IntConsumer; 69 70 /** 71 * This service is meant to be implemented by the app controlling permissions. 72 * 73 * @see PermissionControllerManager 74 * 75 * @hide 76 */ 77 @SystemApi 78 public abstract class PermissionControllerService extends Service { 79 private static final String LOG_TAG = PermissionControllerService.class.getSimpleName(); 80 81 /** 82 * The {@link Intent} action that must be declared as handled by a service 83 * in its manifest for the system to recognize it as a runtime permission 84 * presenter service. 85 */ 86 public static final String SERVICE_INTERFACE = "android.permission.PermissionControllerService"; 87 88 /** 89 * A ChangeId indicating that this device supports camera and mic indicators. Will be "false" 90 * if present, because the CompatChanges#isChangeEnabled method returns true if the change id 91 * is not present. 92 */ 93 @ChangeId 94 @Disabled 95 private static final long CAMERA_MIC_INDICATORS_NOT_PRESENT = 162547999L; 96 97 /** 98 * Revoke a set of runtime permissions for various apps. 99 * 100 * @param requests The permissions to revoke as {@code Map<packageName, List<permission>>} 101 * @param doDryRun Compute the permissions that would be revoked, but not actually revoke them 102 * @param reason Why the permission should be revoked 103 * @param callerPackageName The package name of the calling app 104 * @param callback Callback waiting for the actually removed permissions as 105 * {@code Map<packageName, List<permission>>} 106 */ 107 @BinderThread onRevokeRuntimePermissions( @onNull Map<String, List<String>> requests, boolean doDryRun, @PermissionControllerManager.Reason int reason, @NonNull String callerPackageName, @NonNull Consumer<Map<String, List<String>>> callback)108 public abstract void onRevokeRuntimePermissions( 109 @NonNull Map<String, List<String>> requests, boolean doDryRun, 110 @PermissionControllerManager.Reason int reason, @NonNull String callerPackageName, 111 @NonNull Consumer<Map<String, List<String>>> callback); 112 113 /** 114 * Create a backup of the runtime permissions. 115 * 116 * @param user The user to back up 117 * @param backup The stream to write the backup to 118 * @param callback Callback waiting for operation to be complete 119 */ 120 @BinderThread onGetRuntimePermissionsBackup(@onNull UserHandle user, @NonNull OutputStream backup, @NonNull Runnable callback)121 public abstract void onGetRuntimePermissionsBackup(@NonNull UserHandle user, 122 @NonNull OutputStream backup, @NonNull Runnable callback); 123 124 125 /** 126 * @deprecated Implement {@link #onStageAndApplyRuntimePermissionsBackup} instead 127 */ 128 @Deprecated 129 @BinderThread onRestoreRuntimePermissionsBackup(@onNull UserHandle user, @NonNull InputStream backup, @NonNull Runnable callback)130 public void onRestoreRuntimePermissionsBackup(@NonNull UserHandle user, 131 @NonNull InputStream backup, @NonNull Runnable callback) { 132 } 133 134 /** 135 * Restore a backup of the runtime permissions. 136 * 137 * <p>If an app mentioned in the backup is not installed the state should be saved to later 138 * be restored via {@link #onApplyStagedRuntimePermissionBackup}. 139 * 140 * @param user The user to restore 141 * @param backup The stream to read the backup from 142 * @param callback Callback waiting for operation to be complete 143 */ 144 @BinderThread onStageAndApplyRuntimePermissionsBackup(@onNull UserHandle user, @NonNull InputStream backup, @NonNull Runnable callback)145 public void onStageAndApplyRuntimePermissionsBackup(@NonNull UserHandle user, 146 @NonNull InputStream backup, @NonNull Runnable callback) { 147 onRestoreRuntimePermissionsBackup(user, backup, callback); 148 } 149 150 /** 151 * @deprecated Implement {@link #onApplyStagedRuntimePermissionBackup} instead 152 */ 153 @Deprecated 154 @BinderThread onRestoreDelayedRuntimePermissionsBackup(@onNull String packageName, @NonNull UserHandle user, @NonNull Consumer<Boolean> callback)155 public void onRestoreDelayedRuntimePermissionsBackup(@NonNull String packageName, 156 @NonNull UserHandle user, @NonNull Consumer<Boolean> callback) { 157 } 158 159 /** 160 * Restore the permission state of an app that was provided in 161 * {@link #onStageAndApplyRuntimePermissionsBackup} but could not be restored back then. 162 * 163 * @param packageName The app to restore 164 * @param user The user to restore 165 * @param callback Callback waiting for whether there is still delayed backup left 166 */ 167 @BinderThread onApplyStagedRuntimePermissionBackup(@onNull String packageName, @NonNull UserHandle user, @NonNull Consumer<Boolean> callback)168 public void onApplyStagedRuntimePermissionBackup(@NonNull String packageName, 169 @NonNull UserHandle user, @NonNull Consumer<Boolean> callback) { 170 onRestoreDelayedRuntimePermissionsBackup(packageName, user, callback); 171 } 172 173 /** 174 * Gets the runtime permissions for an app. 175 * 176 * @param packageName The package for which to query. 177 * @param callback Callback waiting for the descriptions of the runtime permissions of the app 178 */ 179 @BinderThread onGetAppPermissions(@onNull String packageName, @NonNull Consumer<List<RuntimePermissionPresentationInfo>> callback)180 public abstract void onGetAppPermissions(@NonNull String packageName, 181 @NonNull Consumer<List<RuntimePermissionPresentationInfo>> callback); 182 183 /** 184 * Revokes the permission {@code permissionName} for app {@code packageName} 185 * 186 * @param packageName The package for which to revoke 187 * @param permissionName The permission to revoke 188 * @param callback Callback waiting for operation to be complete 189 */ 190 @BinderThread onRevokeRuntimePermission(@onNull String packageName, @NonNull String permissionName, @NonNull Runnable callback)191 public abstract void onRevokeRuntimePermission(@NonNull String packageName, 192 @NonNull String permissionName, @NonNull Runnable callback); 193 194 /** 195 * Count how many apps have one of a set of permissions. 196 * 197 * @param permissionNames The permissions the app might have 198 * @param flags Modify which apps to count. By default all non-system apps that request a 199 * permission are counted 200 * @param callback Callback waiting for the number of apps that have one of the permissions 201 */ 202 @BinderThread onCountPermissionApps(@onNull List<String> permissionNames, @CountPermissionAppsFlag int flags, @NonNull IntConsumer callback)203 public abstract void onCountPermissionApps(@NonNull List<String> permissionNames, 204 @CountPermissionAppsFlag int flags, @NonNull IntConsumer callback); 205 206 /** 207 * Count how many apps have used permissions. 208 * 209 * @param countSystem Also count system apps 210 * @param numMillis The number of milliseconds in the past to check for uses 211 * @param callback Callback waiting for the descriptions of the users of permissions 212 */ 213 @BinderThread onGetPermissionUsages(boolean countSystem, long numMillis, @NonNull Consumer<List<RuntimePermissionUsageInfo>> callback)214 public abstract void onGetPermissionUsages(boolean countSystem, long numMillis, 215 @NonNull Consumer<List<RuntimePermissionUsageInfo>> callback); 216 217 /** 218 * Grant or upgrade runtime permissions. The upgrade could be performed 219 * based on whether the device upgraded, whether the permission database 220 * version is old, because the permission policy changed, or because the 221 * permission controller has updated. 222 * 223 * @param callback Callback waiting for operation to be complete 224 * 225 * @see PackageManager#isDeviceUpgrading() 226 * @see PermissionManager#getRuntimePermissionsVersion() 227 * @see PermissionManager#setRuntimePermissionsVersion(int) 228 */ 229 @BinderThread onGrantOrUpgradeDefaultRuntimePermissions(@onNull Runnable callback)230 public abstract void onGrantOrUpgradeDefaultRuntimePermissions(@NonNull Runnable callback); 231 232 233 /** 234 * Called by system to update the 235 * {@link PackageManager}{@code .FLAG_PERMISSION_USER_SENSITIVE_WHEN_*} flags for permissions. 236 * <p> 237 * 238 * If uid is -1, updates the permission flags for all packages. 239 * 240 * Typically called by the system when a new app is installed or updated or when creating a 241 * new user or upgrading either system or permission controller package. 242 * 243 * The callback will be executed by the provided Executor. 244 */ 245 @BinderThread onUpdateUserSensitivePermissionFlags(int uid, @NonNull Executor executor, @NonNull Runnable callback)246 public void onUpdateUserSensitivePermissionFlags(int uid, @NonNull Executor executor, 247 @NonNull Runnable callback) { 248 throw new AbstractMethodError("Must be overridden in implementing class"); 249 } 250 251 /** 252 * Runs {@link #onUpdateUserSensitivePermissionFlags(int, Executor, Runnable)} with the main 253 * executor. 254 */ 255 @BinderThread onUpdateUserSensitivePermissionFlags(int uid, @NonNull Runnable callback)256 public void onUpdateUserSensitivePermissionFlags(int uid, @NonNull Runnable callback) { 257 onUpdateUserSensitivePermissionFlags(uid, getMainExecutor(), callback); 258 } 259 260 /** 261 * @deprecated See {@link #onSetRuntimePermissionGrantStateByDeviceAdmin(String, 262 * AdminPermissionControlParams, Consumer)}. 263 * Set the runtime permission state from a device admin. 264 * 265 * @param callerPackageName The package name of the admin requesting the change 266 * @param packageName Package the permission belongs to 267 * @param permission Permission to change 268 * @param grantState State to set the permission into 269 * @param callback Callback waiting for whether the state could be set or not 270 */ 271 @Deprecated 272 @BinderThread onSetRuntimePermissionGrantStateByDeviceAdmin( @onNull String callerPackageName, @NonNull String packageName, @NonNull String permission, @PermissionGrantState int grantState, @NonNull Consumer<Boolean> callback)273 public abstract void onSetRuntimePermissionGrantStateByDeviceAdmin( 274 @NonNull String callerPackageName, @NonNull String packageName, 275 @NonNull String permission, @PermissionGrantState int grantState, 276 @NonNull Consumer<Boolean> callback); 277 278 /** 279 * Set the runtime permission state from a device admin. 280 * 281 * @param callerPackageName The package name of the admin requesting the change 282 * @param params Parameters of admin request. 283 * @param callback Callback waiting for whether the state could be set or not 284 */ 285 @BinderThread onSetRuntimePermissionGrantStateByDeviceAdmin( @onNull String callerPackageName, @NonNull AdminPermissionControlParams params, @NonNull Consumer<Boolean> callback)286 public void onSetRuntimePermissionGrantStateByDeviceAdmin( 287 @NonNull String callerPackageName, @NonNull AdminPermissionControlParams params, 288 @NonNull Consumer<Boolean> callback) { 289 throw new AbstractMethodError("Must be overridden in implementing class"); 290 } 291 292 /** 293 * Called when a package is considered inactive based on the criteria given by 294 * {@link PermissionManager#startOneTimePermissionSession(String, long, int, int)}. 295 * This method is called at the end of a one-time permission session 296 * 297 * @param packageName The package that has been inactive 298 */ 299 @BinderThread onOneTimePermissionSessionTimeout(@onNull String packageName)300 public void onOneTimePermissionSessionTimeout(@NonNull String packageName) { 301 throw new AbstractMethodError("Must be overridden in implementing class"); 302 } 303 304 /** 305 * Get the platform permissions which belong to a particular permission group 306 * 307 * @param permissionGroupName The permission group whose permissions are desired 308 * @param callback A callback the permission names will be passed to 309 */ 310 @BinderThread onGetPlatformPermissionsForGroup(@onNull String permissionGroupName, @NonNull Consumer<List<String>> callback)311 public void onGetPlatformPermissionsForGroup(@NonNull String permissionGroupName, 312 @NonNull Consumer<List<String>> callback) { 313 throw new AbstractMethodError("Must be overridden in implementing class"); 314 } 315 316 /** 317 * Get the platform group of a particular permission, if the permission is a platform permission 318 * 319 * @param permissionName The permission name whose group is desired 320 * @param callback A callback the group name will be passed to 321 */ 322 @BinderThread onGetGroupOfPlatformPermission(@onNull String permissionName, @NonNull Consumer<String> callback)323 public void onGetGroupOfPlatformPermission(@NonNull String permissionName, 324 @NonNull Consumer<String> callback) { 325 throw new AbstractMethodError("Must be overridden in implementing class"); 326 } 327 /** 328 * Get a user-readable sentence, describing the set of privileges that are to be granted to a 329 * companion app managing a device of the given profile. 330 * 331 * @param deviceProfileName the 332 * {@link android.companion.AssociationRequest.DeviceProfile device profile} name 333 * 334 * @hide 335 */ 336 @SystemApi 337 @RequiresPermission(Manifest.permission.MANAGE_COMPANION_DEVICES) 338 @NonNull getPrivilegesDescriptionStringForProfile(@onNull String deviceProfileName)339 public String getPrivilegesDescriptionStringForProfile(@NonNull String deviceProfileName) { 340 throw new AbstractMethodError("Must be overridden in implementing class"); 341 } 342 343 @Override onBind(Intent intent)344 public final @NonNull IBinder onBind(Intent intent) { 345 return new IPermissionController.Stub() { 346 @Override 347 public void revokeRuntimePermissions( 348 Bundle bundleizedRequest, boolean doDryRun, int reason, 349 String callerPackageName, AndroidFuture callback) { 350 checkNotNull(bundleizedRequest, "bundleizedRequest"); 351 checkNotNull(callerPackageName); 352 checkNotNull(callback); 353 354 Map<String, List<String>> request = new ArrayMap<>(); 355 for (String packageName : bundleizedRequest.keySet()) { 356 Preconditions.checkNotNull(packageName); 357 358 ArrayList<String> permissions = 359 bundleizedRequest.getStringArrayList(packageName); 360 Preconditions.checkCollectionElementsNotNull(permissions, "permissions"); 361 362 request.put(packageName, permissions); 363 } 364 365 enforceSomePermissionsGrantedToCaller( 366 Manifest.permission.REVOKE_RUNTIME_PERMISSIONS); 367 368 // Verify callerPackageName 369 try { 370 PackageInfo pkgInfo = getPackageManager().getPackageInfo(callerPackageName, 0); 371 checkArgument(getCallingUid() == pkgInfo.applicationInfo.uid); 372 } catch (PackageManager.NameNotFoundException e) { 373 throw new RuntimeException(e); 374 } 375 376 onRevokeRuntimePermissions(request, 377 doDryRun, reason, callerPackageName, revoked -> { 378 CollectionUtils.forEach(revoked, (pkg, perms) -> { 379 Preconditions.checkNotNull(pkg); 380 Preconditions.checkCollectionElementsNotNull(perms, "permissions"); 381 }); 382 callback.complete(revoked); 383 }); 384 } 385 386 /** 387 * Throw a {@link SecurityException} if not at least one of the permissions is granted. 388 * 389 * @param requiredPermissions A list of permissions. Any of of them if sufficient to 390 * pass the check 391 */ 392 private void enforceSomePermissionsGrantedToCaller( 393 @NonNull String... requiredPermissions) { 394 for (String requiredPermission : requiredPermissions) { 395 if (checkCallingPermission(requiredPermission) 396 == PackageManager.PERMISSION_GRANTED) { 397 return; 398 } 399 } 400 401 throw new SecurityException( 402 "At lest one of the following permissions is required: " + Arrays.toString( 403 requiredPermissions)); 404 } 405 406 407 @Override 408 public void getRuntimePermissionBackup(UserHandle user, ParcelFileDescriptor pipe) { 409 checkNotNull(user); 410 checkNotNull(pipe); 411 412 enforceSomePermissionsGrantedToCaller(Manifest.permission.GET_RUNTIME_PERMISSIONS); 413 414 try (OutputStream backup = new ParcelFileDescriptor.AutoCloseOutputStream(pipe)) { 415 CountDownLatch latch = new CountDownLatch(1); 416 onGetRuntimePermissionsBackup(user, backup, latch::countDown); 417 latch.await(); 418 } catch (IOException e) { 419 Log.e(LOG_TAG, "Could not open pipe to write backup to", e); 420 } catch (InterruptedException e) { 421 Log.e(LOG_TAG, "getRuntimePermissionBackup timed out", e); 422 } 423 } 424 425 @Override 426 public void stageAndApplyRuntimePermissionsBackup(UserHandle user, 427 ParcelFileDescriptor pipe) { 428 checkNotNull(user); 429 checkNotNull(pipe); 430 431 enforceSomePermissionsGrantedToCaller(Manifest.permission.GRANT_RUNTIME_PERMISSIONS, 432 Manifest.permission.RESTORE_RUNTIME_PERMISSIONS); 433 434 try (InputStream backup = new ParcelFileDescriptor.AutoCloseInputStream(pipe)) { 435 CountDownLatch latch = new CountDownLatch(1); 436 onStageAndApplyRuntimePermissionsBackup(user, backup, latch::countDown); 437 latch.await(); 438 } catch (IOException e) { 439 Log.e(LOG_TAG, "Could not open pipe to read backup from", e); 440 } catch (InterruptedException e) { 441 Log.e(LOG_TAG, "restoreRuntimePermissionBackup timed out", e); 442 } 443 } 444 445 @Override 446 public void applyStagedRuntimePermissionBackup(String packageName, UserHandle user, 447 AndroidFuture callback) { 448 checkNotNull(packageName); 449 checkNotNull(user); 450 checkNotNull(callback); 451 452 enforceSomePermissionsGrantedToCaller(Manifest.permission.GRANT_RUNTIME_PERMISSIONS, 453 Manifest.permission.RESTORE_RUNTIME_PERMISSIONS); 454 455 onApplyStagedRuntimePermissionBackup(packageName, user, callback::complete); 456 } 457 458 @Override 459 public void getAppPermissions(String packageName, AndroidFuture callback) { 460 checkNotNull(packageName, "packageName"); 461 checkNotNull(callback, "callback"); 462 463 enforceSomePermissionsGrantedToCaller(Manifest.permission.GET_RUNTIME_PERMISSIONS); 464 465 onGetAppPermissions(packageName, callback::complete); 466 } 467 468 @Override 469 public void revokeRuntimePermission(String packageName, String permissionName) { 470 checkNotNull(packageName, "packageName"); 471 checkNotNull(permissionName, "permissionName"); 472 473 enforceSomePermissionsGrantedToCaller( 474 Manifest.permission.REVOKE_RUNTIME_PERMISSIONS); 475 476 CountDownLatch latch = new CountDownLatch(1); 477 PermissionControllerService.this.onRevokeRuntimePermission(packageName, 478 permissionName, latch::countDown); 479 try { 480 latch.await(); 481 } catch (InterruptedException e) { 482 Log.e(LOG_TAG, "revokeRuntimePermission timed out", e); 483 } 484 } 485 486 @Override 487 public void countPermissionApps(List<String> permissionNames, int flags, 488 AndroidFuture callback) { 489 checkCollectionElementsNotNull(permissionNames, "permissionNames"); 490 checkFlagsArgument(flags, COUNT_WHEN_SYSTEM | COUNT_ONLY_WHEN_GRANTED); 491 checkNotNull(callback, "callback"); 492 493 enforceSomePermissionsGrantedToCaller(Manifest.permission.GET_RUNTIME_PERMISSIONS); 494 495 onCountPermissionApps(permissionNames, flags, callback::complete); 496 } 497 498 @Override 499 public void getPermissionUsages(boolean countSystem, long numMillis, 500 AndroidFuture callback) { 501 checkArgumentNonnegative(numMillis); 502 checkNotNull(callback, "callback"); 503 504 enforceSomePermissionsGrantedToCaller(Manifest.permission.GET_RUNTIME_PERMISSIONS); 505 506 onGetPermissionUsages(countSystem, numMillis, callback::complete); 507 } 508 509 @Override 510 public void setRuntimePermissionGrantStateByDeviceAdminFromParams( 511 String callerPackageName, AdminPermissionControlParams params, 512 AndroidFuture callback) { 513 checkStringNotEmpty(callerPackageName); 514 if (params.getGrantState() == PERMISSION_GRANT_STATE_GRANTED) { 515 enforceSomePermissionsGrantedToCaller( 516 Manifest.permission.GRANT_RUNTIME_PERMISSIONS); 517 } 518 519 if (params.getGrantState() == PERMISSION_GRANT_STATE_DENIED) { 520 enforceSomePermissionsGrantedToCaller( 521 Manifest.permission.REVOKE_RUNTIME_PERMISSIONS); 522 } 523 524 enforceSomePermissionsGrantedToCaller( 525 Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY); 526 checkNotNull(callback); 527 528 onSetRuntimePermissionGrantStateByDeviceAdmin(callerPackageName, 529 params, callback::complete); 530 } 531 532 @Override 533 public void grantOrUpgradeDefaultRuntimePermissions(@NonNull AndroidFuture callback) { 534 checkNotNull(callback, "callback"); 535 536 enforceSomePermissionsGrantedToCaller( 537 Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY); 538 539 onGrantOrUpgradeDefaultRuntimePermissions(() -> callback.complete(true)); 540 } 541 542 @Override 543 public void updateUserSensitiveForApp(int uid, @NonNull AndroidFuture callback) { 544 Preconditions.checkNotNull(callback, "callback cannot be null"); 545 546 enforceSomePermissionsGrantedToCaller( 547 Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY); 548 549 try { 550 onUpdateUserSensitivePermissionFlags(uid, () -> callback.complete(null)); 551 } catch (Exception e) { 552 callback.completeExceptionally(e); 553 } 554 } 555 556 @Override 557 public void notifyOneTimePermissionSessionTimeout(String packageName) { 558 enforceSomePermissionsGrantedToCaller( 559 Manifest.permission.REVOKE_RUNTIME_PERMISSIONS); 560 packageName = Preconditions.checkNotNull(packageName, 561 "packageName cannot be null"); 562 onOneTimePermissionSessionTimeout(packageName); 563 } 564 565 @Override 566 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 567 checkNotNull(fd, "fd"); 568 checkNotNull(writer, "writer"); 569 570 enforceSomePermissionsGrantedToCaller(Manifest.permission.GET_RUNTIME_PERMISSIONS); 571 572 PermissionControllerService.this.dump(fd, writer, args); 573 } 574 575 @Override 576 public void getPrivilegesDescriptionStringForProfile( 577 @NonNull String deviceProfileName, 578 @NonNull AndroidFuture<String> callback) { 579 try { 580 checkStringNotEmpty(deviceProfileName); 581 Objects.requireNonNull(callback); 582 583 enforceSomePermissionsGrantedToCaller( 584 Manifest.permission.MANAGE_COMPANION_DEVICES); 585 586 callback.complete(PermissionControllerService 587 .this 588 .getPrivilegesDescriptionStringForProfile(deviceProfileName)); 589 } catch (Throwable t) { 590 callback.completeExceptionally(t); 591 } 592 } 593 594 @Override 595 public void getPlatformPermissionsForGroup( 596 @NonNull String permissionName, 597 @NonNull AndroidFuture<List<String>> callback) { 598 try { 599 Objects.requireNonNull(permissionName); 600 Objects.requireNonNull(callback); 601 PermissionControllerService.this.onGetPlatformPermissionsForGroup( 602 permissionName, callback::complete); 603 } catch (Throwable t) { 604 callback.completeExceptionally(t); 605 } 606 } 607 608 @Override 609 public void getGroupOfPlatformPermission( 610 @NonNull String permissionGroupName, 611 @NonNull AndroidFuture<String> callback) { 612 try { 613 Objects.requireNonNull(permissionGroupName); 614 Objects.requireNonNull(callback); 615 PermissionControllerService.this.onGetGroupOfPlatformPermission( 616 permissionGroupName, callback::complete); 617 } catch (Throwable t) { 618 callback.completeExceptionally(t); 619 } 620 } 621 }; 622 } 623 } 624