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