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