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