• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.permission;
18 
19 import static android.companion.virtual.VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT;
20 import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
21 import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE;
22 import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
23 import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
24 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
25 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
26 import static android.os.Build.VERSION_CODES.S;
27 import static android.permission.flags.Flags.FLAG_SHOULD_REGISTER_ATTRIBUTION_SOURCE;
28 import static android.permission.flags.Flags.serverSideAttributionRegistration;
29 
30 import android.Manifest;
31 import android.annotation.CheckResult;
32 import android.annotation.DurationMillisLong;
33 import android.annotation.FlaggedApi;
34 import android.annotation.IntDef;
35 import android.annotation.IntRange;
36 import android.annotation.NonNull;
37 import android.annotation.Nullable;
38 import android.annotation.RequiresPermission;
39 import android.annotation.SdkConstant;
40 import android.annotation.SdkConstant.SdkConstantType;
41 import android.annotation.SystemApi;
42 import android.annotation.SystemService;
43 import android.annotation.TestApi;
44 import android.annotation.UserIdInt;
45 import android.app.ActivityManager;
46 import android.app.ActivityThread;
47 import android.app.AppGlobals;
48 import android.app.AppOpsManager;
49 import android.app.IActivityManager;
50 import android.app.PropertyInvalidatedCache;
51 import android.companion.virtual.VirtualDevice;
52 import android.companion.virtual.VirtualDeviceManager;
53 import android.compat.annotation.ChangeId;
54 import android.compat.annotation.EnabledAfter;
55 import android.content.AttributionSource;
56 import android.content.Context;
57 import android.content.PermissionChecker;
58 import android.content.pm.IPackageManager;
59 import android.content.pm.PackageManager;
60 import android.content.pm.ParceledListSlice;
61 import android.content.pm.PermissionGroupInfo;
62 import android.content.pm.PermissionInfo;
63 import android.content.pm.permission.SplitPermissionInfoParcelable;
64 import android.media.AudioManager;
65 import android.os.Binder;
66 import android.os.Build;
67 import android.os.Handler;
68 import android.os.IBinder;
69 import android.os.Looper;
70 import android.os.Message;
71 import android.os.Parcel;
72 import android.os.Parcelable;
73 import android.os.Process;
74 import android.os.RemoteException;
75 import android.os.ServiceManager;
76 import android.os.SystemClock;
77 import android.os.UserHandle;
78 import android.permission.flags.Flags;
79 import android.text.TextUtils;
80 import android.util.ArrayMap;
81 import android.util.ArraySet;
82 import android.util.DebugUtils;
83 import android.util.Log;
84 import android.util.Slog;
85 
86 import com.android.internal.R;
87 import com.android.internal.annotations.Immutable;
88 import com.android.internal.util.CollectionUtils;
89 import com.android.modules.utils.build.SdkLevel;
90 
91 import java.lang.annotation.Retention;
92 import java.lang.annotation.RetentionPolicy;
93 import java.util.ArrayList;
94 import java.util.Collections;
95 import java.util.List;
96 import java.util.Map;
97 import java.util.Objects;
98 import java.util.Set;
99 
100 /**
101  * System level service for accessing the permission capabilities of the platform.
102  *
103  * @hide
104  */
105 @SystemApi
106 @SystemService(Context.PERMISSION_SERVICE)
107 public final class PermissionManager {
108     private static final String LOG_TAG = PermissionManager.class.getName();
109 
110     /**
111      * The permission is granted.
112      */
113     public static final int PERMISSION_GRANTED = 0;
114 
115     /**
116      * The permission is denied. Applicable only to runtime permissions.
117      * <p>
118      * The app isn't expecting the permission to be denied so that a "no-op" action should be taken,
119      * such as returning an empty result.
120      */
121     public static final int PERMISSION_SOFT_DENIED = 1;
122 
123     /**
124      * The permission is denied.
125      * <p>
126      * The app should receive a {@code SecurityException}, or an error through a relevant callback.
127      */
128     public static final int PERMISSION_HARD_DENIED = 2;
129 
130     /** @hide */
131     @IntDef(prefix = { "PERMISSION_" }, value = {
132             PERMISSION_GRANTED,
133             PERMISSION_SOFT_DENIED,
134             PERMISSION_HARD_DENIED
135     })
136     @Retention(RetentionPolicy.SOURCE)
137     public @interface PermissionResult {}
138 
139     /**
140      * The set of flags that indicate that a permission state has been explicitly set
141      *
142      * @hide
143      */
144     public static final int EXPLICIT_SET_FLAGS = FLAG_PERMISSION_USER_SET
145             | FLAG_PERMISSION_USER_FIXED | FLAG_PERMISSION_POLICY_FIXED
146             | FLAG_PERMISSION_SYSTEM_FIXED | FLAG_PERMISSION_GRANTED_BY_DEFAULT
147             | FLAG_PERMISSION_GRANTED_BY_ROLE;
148 
149     /**
150      * Activity action: Launch UI to review permission decisions.
151      * <p>
152      * <strong>Important:</strong>You must protect the activity that handles this action with the
153      * {@link android.Manifest.permission#START_REVIEW_PERMISSION_DECISIONS} permission to ensure
154      * that only the system can launch this activity. The system will not launch activities that are
155      * not properly protected.
156      * <p>
157      * Input: Nothing.
158      * </p>
159      * <p>
160      * Output: Nothing.
161      * </p>
162      */
163     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
164     @RequiresPermission(android.Manifest.permission.START_REVIEW_PERMISSION_DECISIONS)
165     public static final String ACTION_REVIEW_PERMISSION_DECISIONS =
166             "android.permission.action.REVIEW_PERMISSION_DECISIONS";
167 
168 
169     /** @hide */
170     public static final String LOG_TAG_TRACE_GRANTS = "PermissionGrantTrace";
171 
172     /** @hide */
173     public static final String KILL_APP_REASON_PERMISSIONS_REVOKED =
174             "permissions revoked";
175     /** @hide */
176     public static final String KILL_APP_REASON_GIDS_CHANGED =
177             "permission grant or revoke changed gids";
178 
179     private static final String SYSTEM_PKG = "android";
180 
181     /**
182      * Refuse to install package if groups of permissions are bad
183      * - Permission groups should only be shared between apps sharing a certificate
184      * - If a permission belongs to a group that group should be defined
185      *
186      * @hide
187      */
188     @ChangeId
189     @EnabledAfter(targetSdkVersion = S)
190     public static final long CANNOT_INSTALL_WITH_BAD_PERMISSION_GROUPS = 146211400;
191 
192     /**
193      * Whether to use the new {@link com.android.server.permission.access.AccessCheckingService}.
194      *
195      * @hide
196      */
197     public static final boolean USE_ACCESS_CHECKING_SERVICE = SdkLevel.isAtLeastV();
198 
199     /**
200      * The time to wait in between refreshing the exempted indicator role packages
201      */
202     private static final long EXEMPTED_INDICATOR_ROLE_UPDATE_FREQUENCY_MS = 15000;
203 
204     private static long sLastIndicatorUpdateTime = -1;
205 
206     private static final int[] EXEMPTED_ROLES = {R.string.config_systemAmbientAudioIntelligence,
207         R.string.config_systemUiIntelligence, R.string.config_systemAudioIntelligence,
208         R.string.config_systemNotificationIntelligence, R.string.config_systemTextIntelligence,
209         R.string.config_systemVisualIntelligence};
210 
211     private static final String[] INDICATOR_EXEMPTED_PACKAGES = new String[EXEMPTED_ROLES.length];
212 
213     /**
214      * Note: Changing this won't do anything on its own - you should also change the filtering in
215      * {@link #shouldTraceGrant}.
216      *
217      * See log output for tag {@link #LOG_TAG_TRACE_GRANTS}
218      *
219      * @hide
220      */
221     public static final boolean DEBUG_TRACE_GRANTS = false;
222     /**
223      * @hide
224      */
225     public static final boolean DEBUG_TRACE_PERMISSION_UPDATES = false;
226 
227     /**
228      * Additional debug log for virtual device permissions.
229      * @hide
230      */
231     public static final boolean DEBUG_DEVICE_PERMISSIONS = false;
232 
233     /**
234      * Intent extra: List of PermissionGroupUsages
235      * <p>
236      * Type: {@code List<PermissionGroupUsage>}
237      * </p>
238      * @hide
239      */
240     @SystemApi
241     public static final String EXTRA_PERMISSION_USAGES =
242             "android.permission.extra.PERMISSION_USAGES";
243 
244     /**
245      * Specify what permissions are device aware. Only device aware permissions can be granted to
246      * a remote device.
247      * @hide
248      */
249     public static final Set<String> DEVICE_AWARE_PERMISSIONS =
250             Flags.deviceAwarePermissionsEnabled()
251                     ? Set.of(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
252                     : Collections.emptySet();
253 
254     private final @NonNull Context mContext;
255 
256     private final IPackageManager mPackageManager;
257 
258     private final IPermissionManager mPermissionManager;
259 
260     private final LegacyPermissionManager mLegacyPermissionManager;
261 
262     private final ArrayMap<PackageManager.OnPermissionsChangedListener,
263             IOnPermissionsChangeListener> mPermissionListeners = new ArrayMap<>();
264     private PermissionUsageHelper mUsageHelper;
265 
266     private List<SplitPermissionInfo> mSplitPermissionInfos;
267 
268     /**
269      * Creates a new instance.
270      *
271      * @param context The current context in which to operate
272      *
273      * @hide
274      */
PermissionManager(@onNull Context context)275     public PermissionManager(@NonNull Context context)
276             throws ServiceManager.ServiceNotFoundException {
277         mContext = context;
278         mPackageManager = AppGlobals.getPackageManager();
279         mPermissionManager = IPermissionManager.Stub.asInterface(ServiceManager.getServiceOrThrow(
280                 "permissionmgr"));
281         mLegacyPermissionManager = context.getSystemService(LegacyPermissionManager.class);
282     }
283 
284     /**
285      * Checks whether a given data access chain described by the given {@link AttributionSource}
286      * has a given permission.
287      *
288      * <strong>NOTE:</strong> Use this method only for permission checks at the
289      * point where you will deliver the permission protected data to clients.
290      *
291      * <p>For example, if an app registers a location listener it should have the location
292      * permission but no data is actually sent to the app at the moment of registration
293      * and you should use {@link #checkPermissionForPreflight(String, AttributionSource)}
294      * to determine if the app has or may have location permission (if app has only foreground
295      * location the grant state depends on the app's fg/gb state) and this check will not
296      * leave a trace that permission protected data was delivered. When you are about to
297      * deliver the location data to a registered listener you should use this method which
298      * will evaluate the permission access based on the current fg/bg state of the app and
299      * leave a record that the data was accessed.
300      *
301      * <p>Requires the start of the AttributionSource chain to have the UPDATE_APP_OPS_STATS
302      * permission for the app op accesses to be given the TRUSTED_PROXY/PROXIED flags, otherwise the
303      * accesses will have the UNTRUSTED flags.
304      *
305      * @param permission The permission to check.
306      * @param attributionSource the permission identity
307      * @param message A message describing the reason the permission was checked
308      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
309      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
310      *
311      * @see #checkPermissionForPreflight(String, AttributionSource)
312      */
313     @PermissionResult
314     @RequiresPermission(value = Manifest.permission.UPDATE_APP_OPS_STATS, conditional = true)
checkPermissionForDataDelivery(@onNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message)315     public int checkPermissionForDataDelivery(@NonNull String permission,
316             @NonNull AttributionSource attributionSource, @Nullable String message) {
317         return PermissionChecker.checkPermissionForDataDelivery(mContext, permission,
318                 // FIXME(b/199526514): PID should be passed inside AttributionSource.
319                 PermissionChecker.PID_UNKNOWN, attributionSource, message);
320     }
321 
322     /**
323      *
324      * Similar to checkPermissionForDataDelivery, except it results in an app op start, rather than
325      * a note. If this method is used, then {@link #finishDataDelivery(String, AttributionSource)}
326      * must be used when access is finished.
327      *
328      * @param permission The permission to check.
329      * @param attributionSource the permission identity
330      * @param message A message describing the reason the permission was checked
331      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
332      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
333      *
334      * <p>Requires the start of the AttributionSource chain to have the UPDATE_APP_OPS_STATS
335      * permission for the app op accesses to be given the TRUSTED_PROXY/PROXIED flags, otherwise the
336      * accesses will have the UNTRUSTED flags.
337      *
338      * @see #checkPermissionForDataDelivery(String, AttributionSource, String)
339      */
340     @PermissionResult
341     @RequiresPermission(value = Manifest.permission.UPDATE_APP_OPS_STATS, conditional = true)
checkPermissionForStartDataDelivery(@onNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message)342     public int checkPermissionForStartDataDelivery(@NonNull String permission,
343             @NonNull AttributionSource attributionSource, @Nullable String message) {
344         return PermissionChecker.checkPermissionForDataDelivery(mContext, permission,
345                 // FIXME(b/199526514): PID should be passed inside AttributionSource.
346                 PermissionChecker.PID_UNKNOWN, attributionSource, message, true);
347     }
348 
349     /**
350      * Indicate that usage has finished for an {@link AttributionSource} started with
351      * {@link #checkPermissionForStartDataDelivery(String, AttributionSource, String)}
352      *
353      * @param permission The permission to check.
354      * @param attributionSource the permission identity to finish
355      */
finishDataDelivery(@onNull String permission, @NonNull AttributionSource attributionSource)356     public void finishDataDelivery(@NonNull String permission,
357             @NonNull AttributionSource attributionSource) {
358         PermissionChecker.finishDataDelivery(mContext, AppOpsManager.permissionToOp(permission),
359                 attributionSource);
360     }
361 
362     /**
363      * Checks whether a given data access chain described by the given {@link AttributionSource}
364      * has a given permission. Call this method if you are the datasource which would not blame you
365      * for access to the data since you are the data. Use this API if you are the datasource of the
366      * protected state.
367      *
368      * <strong>NOTE:</strong> Use this method only for permission checks at the
369      * point where you will deliver the permission protected data to clients.
370      *
371      * <p>For example, if an app registers a location listener it should have the location
372      * permission but no data is actually sent to the app at the moment of registration
373      * and you should use {@link #checkPermissionForPreflight(String, AttributionSource)}
374      * to determine if the app has or may have location permission (if app has only foreground
375      * location the grant state depends on the app's fg/gb state) and this check will not
376      * leave a trace that permission protected data was delivered. When you are about to
377      * deliver the location data to a registered listener you should use this method which
378      * will evaluate the permission access based on the current fg/bg state of the app and
379      * leave a record that the data was accessed.
380      *
381      * <p>Requires the start of the AttributionSource chain to have the UPDATE_APP_OPS_STATS
382      * permission for the app op accesses to be given the TRUSTED_PROXY/PROXIED flags, otherwise the
383      * accesses will have the UNTRUSTED flags.
384      *
385      * @param permission The permission to check.
386      * @param attributionSource the permission identity
387      * @param message A message describing the reason the permission was checked
388      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
389      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
390      *
391      * @see #checkPermissionForPreflight(String, AttributionSource)
392      */
393     @PermissionResult
394     @RequiresPermission(value = Manifest.permission.UPDATE_APP_OPS_STATS, conditional = true)
checkPermissionForDataDeliveryFromDataSource(@onNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message)395     public int checkPermissionForDataDeliveryFromDataSource(@NonNull String permission,
396             @NonNull AttributionSource attributionSource, @Nullable String message) {
397         return PermissionChecker.checkPermissionForDataDeliveryFromDataSource(mContext, permission,
398                 PermissionChecker.PID_UNKNOWN, attributionSource, message);
399     }
400 
401     /**
402      * Checks whether a given data access chain described by the given {@link AttributionSource}
403      * has a given permission.
404      *
405      * <strong>NOTE:</strong> Use this method only for permission checks at the
406      * preflight point where you will not deliver the permission protected data
407      * to clients but schedule permission data delivery, apps register listeners,
408      * etc.
409      *
410      * <p>For example, if an app registers a data listener it should have the required
411      * permission but no data is actually sent to the app at the moment of registration
412      * and you should use this method to determine if the app has or may have the
413      * permission and this check will not leave a trace that permission protected data
414      * was delivered. When you are about to deliver the protected data to a registered
415      * listener you should use {@link #checkPermissionForDataDelivery(String,
416      * AttributionSource, String)} which will evaluate the permission access based
417      * on the current fg/bg state of the app and leave a record that the data was accessed.
418      *
419      * @param permission The permission to check.
420      * @param attributionSource The identity for which to check the permission.
421      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
422      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
423      */
424     @PermissionResult
checkPermissionForPreflight(@onNull String permission, @NonNull AttributionSource attributionSource)425     public int checkPermissionForPreflight(@NonNull String permission,
426             @NonNull AttributionSource attributionSource) {
427         return PermissionChecker.checkPermissionForPreflight(mContext, permission,
428                 attributionSource);
429     }
430 
431     /**
432      * Retrieve all of the information we know about a particular permission.
433      *
434      * @param permissionName the fully qualified name (e.g. com.android.permission.LOGIN) of the
435      *                       permission you are interested in
436      * @param flags additional option flags to modify the data returned
437      * @return a {@link PermissionInfo} containing information about the permission, or {@code null}
438      *         if not found
439      *
440      * @hide Pending API
441      */
442     @Nullable
getPermissionInfo(@onNull String permissionName, @PackageManager.PermissionInfoFlags int flags)443     public PermissionInfo getPermissionInfo(@NonNull String permissionName,
444             @PackageManager.PermissionInfoFlags int flags) {
445         try {
446             final String packageName = mContext.getOpPackageName();
447             return mPermissionManager.getPermissionInfo(permissionName, packageName, flags);
448         } catch (RemoteException e) {
449             throw e.rethrowFromSystemServer();
450         }
451     }
452 
453     /**
454      * Query for all of the permissions associated with a particular group.
455      *
456      * @param groupName the fully qualified name (e.g. com.android.permission.LOGIN) of the
457      *                  permission group you are interested in. Use {@code null} to find all of the
458      *                  permissions not associated with a group
459      * @param flags additional option flags to modify the data returned
460      * @return a list of {@link PermissionInfo} containing information about all of the permissions
461      *         in the given group, or {@code null} if the group is not found
462      *
463      * @hide Pending API
464      */
465     @Nullable
queryPermissionsByGroup(@ullable String groupName, @PackageManager.PermissionInfoFlags int flags)466     public List<PermissionInfo> queryPermissionsByGroup(@Nullable String groupName,
467             @PackageManager.PermissionInfoFlags int flags) {
468         try {
469             final ParceledListSlice<PermissionInfo> parceledList =
470                     mPermissionManager.queryPermissionsByGroup(groupName, flags);
471             if (parceledList == null) {
472                 return null;
473             }
474             return parceledList.getList();
475         } catch (RemoteException e) {
476             throw e.rethrowFromSystemServer();
477         }
478     }
479 
480     /**
481      * Add a new dynamic permission to the system. For this to work, your package must have defined
482      * a permission tree through the
483      * {@link android.R.styleable#AndroidManifestPermissionTree &lt;permission-tree&gt;} tag in its
484      * manifest. A package can only add permissions to trees that were defined by either its own
485      * package or another with the same user id; a permission is in a tree if it matches the name of
486      * the permission tree + ".": for example, "com.foo.bar" is a member of the permission tree
487      * "com.foo".
488      * <p>
489      * It is good to make your permission tree name descriptive, because you are taking possession
490      * of that entire set of permission names. Thus, it must be under a domain you control, with a
491      * suffix that will not match any normal permissions that may be declared in any applications
492      * that are part of that domain.
493      * <p>
494      * New permissions must be added before any .apks are installed that use those permissions.
495      * Permissions you add through this method are remembered across reboots of the device. If the
496      * given permission already exists, the info you supply here will be used to update it.
497      *
498      * @param permissionInfo description of the permission to be added
499      * @param async whether the persistence of the permission should be asynchronous, allowing it to
500      *              return quicker and batch a series of adds, at the expense of no guarantee the
501      *              added permission will be retained if the device is rebooted before it is
502      *              written.
503      * @return {@code true} if a new permission was created, {@code false} if an existing one was
504      *         updated
505      * @throws SecurityException if you are not allowed to add the given permission name
506      *
507      * @see #removePermission(String)
508      *
509      * @hide Pending API
510      */
addPermission(@onNull PermissionInfo permissionInfo, boolean async)511     public boolean addPermission(@NonNull PermissionInfo permissionInfo, boolean async) {
512         try {
513             return mPermissionManager.addPermission(permissionInfo, async);
514         } catch (RemoteException e) {
515             throw e.rethrowFromSystemServer();
516         }
517     }
518 
519     /**
520      * Removes a permission that was previously added with
521      * {@link #addPermission(PermissionInfo, boolean)}. The same ownership rules apply -- you are
522      * only allowed to remove permissions that you are allowed to add.
523      *
524      * @param permissionName the name of the permission to remove
525      * @throws SecurityException if you are not allowed to remove the given permission name
526      *
527      * @see #addPermission(PermissionInfo, boolean)
528      *
529      * @hide Pending API
530      */
removePermission(@onNull String permissionName)531     public void removePermission(@NonNull String permissionName) {
532         try {
533             mPermissionManager.removePermission(permissionName);
534         } catch (RemoteException e) {
535             throw e.rethrowFromSystemServer();
536         }
537     }
538 
539     /**
540      * Retrieve all of the information we know about a particular group of permissions.
541      *
542      * @param groupName the fully qualified name (e.g. com.android.permission_group.APPS) of the
543      *                  permission you are interested in
544      * @param flags additional option flags to modify the data returned
545      * @return a {@link PermissionGroupInfo} containing information about the permission, or
546      *         {@code null} if not found
547      *
548      * @hide Pending API
549      */
550     @Nullable
getPermissionGroupInfo(@onNull String groupName, @PackageManager.PermissionGroupInfoFlags int flags)551     public PermissionGroupInfo getPermissionGroupInfo(@NonNull String groupName,
552             @PackageManager.PermissionGroupInfoFlags int flags) {
553         try {
554             return mPermissionManager.getPermissionGroupInfo(groupName, flags);
555         } catch (RemoteException e) {
556             throw e.rethrowFromSystemServer();
557         }
558     }
559 
560     /**
561      * Retrieve all of the known permission groups in the system.
562      *
563      * @param flags additional option flags to modify the data returned
564      * @return a list of {@link PermissionGroupInfo} containing information about all of the known
565      *         permission groups
566      *
567      * @hide Pending API
568      */
569     @NonNull
getAllPermissionGroups( @ackageManager.PermissionGroupInfoFlags int flags)570     public List<PermissionGroupInfo> getAllPermissionGroups(
571             @PackageManager.PermissionGroupInfoFlags int flags) {
572         try {
573             final ParceledListSlice<PermissionGroupInfo> parceledList =
574                     mPermissionManager.getAllPermissionGroups(flags);
575             if (parceledList == null) {
576                 return Collections.emptyList();
577             }
578             return parceledList.getList();
579         } catch (RemoteException e) {
580             throw e.rethrowFromSystemServer();
581         }
582     }
583 
584     /**
585      * Checks whether a particular permissions has been revoked for a package by policy. Typically
586      * the device owner or the profile owner may apply such a policy. The user cannot grant policy
587      * revoked permissions, hence the only way for an app to get such a permission is by a policy
588      * change.
589      *
590      * @param packageName the name of the package you are checking against
591      * @param permissionName the name of the permission you are checking for
592      *
593      * @return whether the permission is restricted by policy
594      *
595      * @hide Pending API
596      */
597     @CheckResult
isPermissionRevokedByPolicy(@onNull String packageName, @NonNull String permissionName)598     public boolean isPermissionRevokedByPolicy(@NonNull String packageName,
599             @NonNull String permissionName) {
600         try {
601             return mPermissionManager.isPermissionRevokedByPolicy(packageName, permissionName,
602                     mContext.getDeviceId(), mContext.getUserId());
603         } catch (RemoteException e) {
604             throw e.rethrowFromSystemServer();
605         }
606     }
607 
608     /** @hide */
shouldTraceGrant( @onNull String packageName, @NonNull String permissionName, int userId)609     public static boolean shouldTraceGrant(
610             @NonNull String packageName, @NonNull String permissionName, int userId) {
611         // To be modified when debugging
612         // template: if ("".equals(packageName) && "".equals(permissionName)) return true;
613         return false;
614     }
615 
616     /**
617      * Grant a runtime permission to an application which the application does not already have. The
618      * permission must have been requested by the application. If the application is not allowed to
619      * hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or
620      * permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown.
621      * <p>
622      * <strong>Note: </strong>Using this API requires holding
623      * {@code android.permission.GRANT_RUNTIME_PERMISSIONS} and if the user ID is not the current
624      * user {@code android.permission.INTERACT_ACROSS_USERS_FULL}.
625      *
626      * @param packageName the package to which to grant the permission
627      * @param permissionName the permission name to grant
628      * @param user the user for which to grant the permission
629      *
630      * @see #revokeRuntimePermission(String, String, android.os.UserHandle, String)
631      *
632      * @hide
633      */
634     @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
635     //@SystemApi
grantRuntimePermission(@onNull String packageName, @NonNull String permissionName, @NonNull UserHandle user)636     public void grantRuntimePermission(@NonNull String packageName,
637             @NonNull String permissionName, @NonNull UserHandle user) {
638         String persistentDeviceId = getPersistentDeviceId(mContext.getDeviceId());
639         if (persistentDeviceId == null) {
640             return;
641         }
642 
643         grantRuntimePermissionInternal(packageName, permissionName, persistentDeviceId, user);
644     }
645 
646     /**
647      * Grant a runtime permission to an application which the application does not already have. The
648      * permission must have been requested by the application. If the application is not allowed to
649      * hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or
650      * permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown.
651      *
652      * @param packageName the package to which to grant the permission
653      * @param permissionName the permission name to grant
654      * @param persistentDeviceId the device Id to which to grant the permission
655      *
656      * @see #revokeRuntimePermission(String, String, String, String)
657      *
658      * @hide
659      */
660     @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
661     @SystemApi
662     @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
grantRuntimePermission(@onNull String packageName, @NonNull String permissionName, @NonNull String persistentDeviceId)663     public void grantRuntimePermission(@NonNull String packageName,
664             @NonNull String permissionName, @NonNull String persistentDeviceId) {
665         grantRuntimePermissionInternal(packageName, permissionName, persistentDeviceId,
666                 mContext.getUser());
667     }
668 
grantRuntimePermissionInternal(@onNull String packageName, @NonNull String permissionName, @NonNull String persistentDeviceId, @NonNull UserHandle user)669     private void grantRuntimePermissionInternal(@NonNull String packageName,
670             @NonNull String permissionName, @NonNull String persistentDeviceId,
671             @NonNull UserHandle user) {
672         if (DEBUG_TRACE_GRANTS
673                 && shouldTraceGrant(packageName, permissionName, user.getIdentifier())) {
674             Log.i(LOG_TAG_TRACE_GRANTS, "App " + mContext.getPackageName() + " is granting "
675                     + packageName + " "
676                     + permissionName + " for user " + user.getIdentifier()
677                     + " for persistent device " + persistentDeviceId, new RuntimeException());
678         }
679         try {
680             mPermissionManager.grantRuntimePermission(packageName, permissionName,
681                     persistentDeviceId, user.getIdentifier());
682         } catch (RemoteException e) {
683             throw e.rethrowFromSystemServer();
684         }
685     }
686 
687     /**
688      * Revoke a runtime permission that was previously granted by
689      * {@link #grantRuntimePermission(String, String, android.os.UserHandle)}. The permission must
690      * have been requested by and granted to the application. If the application is not allowed to
691      * hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or
692      * permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown.
693      * <p>
694      * <strong>Note: </strong>Using this API requires holding
695      * {@code android.permission.REVOKE_RUNTIME_PERMISSIONS} and if the user ID is not the current
696      * user {@code android.permission.INTERACT_ACROSS_USERS_FULL}.
697      *
698      * @param packageName the package from which to revoke the permission
699      * @param permissionName the permission name to revoke
700      * @param user the user for which to revoke the permission
701      * @param reason the reason for the revoke, or {@code null} for unspecified
702      *
703      * @see #grantRuntimePermission(String, String, android.os.UserHandle)
704      *
705      * @hide
706      */
707     @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
708     //@SystemApi
revokeRuntimePermission(@onNull String packageName, @NonNull String permissionName, @NonNull UserHandle user, @Nullable String reason)709     public void revokeRuntimePermission(@NonNull String packageName,
710             @NonNull String permissionName, @NonNull UserHandle user, @Nullable String reason) {
711         String persistentDeviceId = getPersistentDeviceId(mContext.getDeviceId());
712         if (persistentDeviceId == null) {
713             return;
714         }
715 
716         revokeRuntimePermissionInternal(packageName, permissionName, persistentDeviceId, user,
717                 reason);
718     }
719 
720     /**
721      * Revoke a runtime permission that was previously granted by
722      * {@link #grantRuntimePermission(String, String, String)}. The permission must
723      * have been requested by and granted to the application. If the application is not allowed to
724      * hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or
725      * permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown.
726      *
727      * @param packageName the package from which to revoke the permission
728      * @param permissionName the permission name to revoke
729      * @param persistentDeviceId the persistent device id for which to revoke the permission
730      * @param reason the reason for the revoke, or {@code null} for unspecified
731      *
732      * @see #grantRuntimePermission(String, String, String)
733      *
734      * @hide
735      */
736     @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
737     @SystemApi
738     @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
revokeRuntimePermission(@onNull String packageName, @NonNull String permissionName, @NonNull String persistentDeviceId, @Nullable String reason)739     public void revokeRuntimePermission(@NonNull String packageName,
740             @NonNull String permissionName, @NonNull String persistentDeviceId,
741             @Nullable String reason) {
742         revokeRuntimePermissionInternal(packageName, permissionName, persistentDeviceId,
743                 mContext.getUser(), reason);
744     }
745 
revokeRuntimePermissionInternal(@onNull String packageName, @NonNull String permissionName, @NonNull String persistentDeviceId, @NonNull UserHandle user, @Nullable String reason)746     private void revokeRuntimePermissionInternal(@NonNull String packageName,
747             @NonNull String permissionName, @NonNull String persistentDeviceId,
748             @NonNull UserHandle user, @Nullable String reason) {
749         if (DEBUG_TRACE_PERMISSION_UPDATES
750                 && shouldTraceGrant(packageName, permissionName, user.getIdentifier())) {
751             Log.i(LOG_TAG, "App " + mContext.getPackageName() + " is revoking " + packageName + " "
752                     + permissionName + " for user " + user.getIdentifier()
753                     + " for persistent device "
754                     + persistentDeviceId + " with reason "
755                     + reason, new RuntimeException());
756         }
757         try {
758             mPermissionManager.revokeRuntimePermission(packageName, permissionName,
759                     persistentDeviceId, user.getIdentifier(), reason);
760         } catch (RemoteException e) {
761             throw e.rethrowFromSystemServer();
762         }
763     }
764 
765     /**
766      * Gets the state flags associated with a permission.
767      *
768      * @param packageName the package name for which to get the flags
769      * @param permissionName the permission for which to get the flags
770      * @param user the user for which to get permission flags
771      * @return the permission flags
772      *
773      * @hide
774      */
775     @PackageManager.PermissionFlags
776     @RequiresPermission(anyOf = {
777             android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
778             android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
779             android.Manifest.permission.GET_RUNTIME_PERMISSIONS
780     })
781     //@SystemApi
getPermissionFlags(@onNull String packageName, @NonNull String permissionName, @NonNull UserHandle user)782     public int getPermissionFlags(@NonNull String packageName, @NonNull String permissionName,
783             @NonNull UserHandle user) {
784         String persistentDeviceId = getPersistentDeviceId(mContext.getDeviceId());
785         if (persistentDeviceId == null) {
786             return 0;
787         }
788 
789         return getPermissionFlagsInternal(packageName, permissionName, persistentDeviceId, user);
790     }
791 
792     /**
793      * Gets the state flags associated with a permission.
794      *
795      * @param packageName the package name for which to get the flags
796      * @param permissionName the permission for which to get the flags
797      * @param persistentDeviceId the persistent device Id for which to get permission flags
798      * @return the permission flags
799      *
800      * @hide
801      */
802     @PackageManager.PermissionFlags
803     @RequiresPermission(anyOf = {
804             android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
805             android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
806             android.Manifest.permission.GET_RUNTIME_PERMISSIONS
807     })
808     @SystemApi
809     @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
getPermissionFlags(@onNull String packageName, @NonNull String permissionName, @NonNull String persistentDeviceId)810     public int getPermissionFlags(@NonNull String packageName, @NonNull String permissionName,
811             @NonNull String persistentDeviceId) {
812         return getPermissionFlagsInternal(packageName, permissionName, persistentDeviceId,
813                 mContext.getUser());
814     }
815 
getPermissionFlagsInternal(@onNull String packageName, @NonNull String permissionName, @NonNull String persistentDeviceId, @NonNull UserHandle user)816     private int getPermissionFlagsInternal(@NonNull String packageName,
817             @NonNull String permissionName, @NonNull String persistentDeviceId,
818             @NonNull UserHandle user) {
819         try {
820             return mPermissionManager.getPermissionFlags(packageName, permissionName,
821                     persistentDeviceId, user.getIdentifier());
822         } catch (RemoteException e) {
823             throw e.rethrowFromSystemServer();
824         }
825     }
826 
827     /**
828      * Updates the flags associated with a permission by replacing the flags in the specified mask
829      * with the provided flag values.
830      *
831      * @param packageName The package name for which to update the flags
832      * @param permissionName The permission for which to update the flags
833      * @param flagMask The flags which to replace
834      * @param flagValues The flags with which to replace
835      * @param user The user for which to update the permission flags
836      *
837      * @hide
838      */
839     @RequiresPermission(anyOf = {
840             android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
841             android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
842     })
843     //@SystemApi
updatePermissionFlags(@onNull String packageName, @NonNull String permissionName, @PackageManager.PermissionFlags int flagMask, @PackageManager.PermissionFlags int flagValues, @NonNull UserHandle user)844     public void updatePermissionFlags(@NonNull String packageName, @NonNull String permissionName,
845             @PackageManager.PermissionFlags int flagMask,
846             @PackageManager.PermissionFlags int flagValues, @NonNull UserHandle user) {
847         String persistentDeviceId = getPersistentDeviceId(mContext.getDeviceId());
848         if (persistentDeviceId == null) {
849             return;
850         }
851 
852         updatePermissionFlagsInternal(packageName, permissionName, flagMask, flagValues,
853                 persistentDeviceId, user);
854     }
855 
856     /**
857      * Updates the flags associated with a permission by replacing the flags in the specified mask
858      * with the provided flag values.
859      *
860      * @param packageName The package name for which to update the flags
861      * @param permissionName The permission for which to update the flags
862      * @param persistentDeviceId The persistent device for which to update the permission flags
863      * @param flagMask The flags which to replace
864      * @param flagValues The flags with which to replace
865      *
866      * @hide
867      */
868     @RequiresPermission(anyOf = {
869             android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
870             android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
871     })
872     @SystemApi
873     @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
updatePermissionFlags(@onNull String packageName, @NonNull String permissionName, @NonNull String persistentDeviceId, @PackageManager.PermissionFlags int flagMask, @PackageManager.PermissionFlags int flagValues )874     public void updatePermissionFlags(@NonNull String packageName, @NonNull String permissionName,
875             @NonNull String persistentDeviceId,
876             @PackageManager.PermissionFlags int flagMask,
877             @PackageManager.PermissionFlags int flagValues
878     ) {
879         updatePermissionFlagsInternal(packageName, permissionName, flagMask, flagValues,
880                 persistentDeviceId, mContext.getUser());
881     }
882 
updatePermissionFlagsInternal(@onNull String packageName, @NonNull String permissionName, @PackageManager.PermissionFlags int flagMask, @PackageManager.PermissionFlags int flagValues, @NonNull String persistentDeviceId, @NonNull UserHandle user )883     private void updatePermissionFlagsInternal(@NonNull String packageName,
884             @NonNull String permissionName,
885             @PackageManager.PermissionFlags int flagMask,
886             @PackageManager.PermissionFlags int flagValues, @NonNull String persistentDeviceId,
887             @NonNull UserHandle user
888     ) {
889         if (DEBUG_TRACE_PERMISSION_UPDATES && shouldTraceGrant(packageName, permissionName,
890                 user.getIdentifier())) {
891             Log.i(LOG_TAG, "App " + mContext.getPackageName() + " is updating flags for "
892                     + packageName + " " + permissionName + " for user "
893                     + user.getIdentifier() + " for persistentDeviceId " + persistentDeviceId + ": "
894                     + DebugUtils.flagsToString(PackageManager.class, "FLAG_PERMISSION_", flagMask)
895                     + " := " + DebugUtils.flagsToString(PackageManager.class, "FLAG_PERMISSION_",
896                             flagValues), new RuntimeException());
897         }
898         try {
899             final boolean checkAdjustPolicyFlagPermission =
900                     mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q;
901             mPermissionManager.updatePermissionFlags(packageName, permissionName, flagMask,
902                     flagValues, checkAdjustPolicyFlagPermission,
903                     persistentDeviceId, user.getIdentifier());
904         } catch (RemoteException e) {
905             throw e.rethrowFromSystemServer();
906         }
907     }
908 
909     /**
910      * Gets the restricted permissions that have been allowlisted and the app is allowed to have
911      * them granted in their full form.
912      * <p>
913      * Permissions can be hard restricted which means that the app cannot hold them or soft
914      * restricted where the app can hold the permission but in a weaker form. Whether a permission
915      * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or
916      * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission
917      * declaration. Allowlisting a hard restricted permission allows for the to hold that permission
918      * and allowlisting a soft restricted permission allows the app to hold the permission in its
919      * full, unrestricted form.
920      * <p>
921      * There are four allowlists:
922      * <ol>
923      * <li>
924      * One for cases where the system permission policy allowlists a permission. This list
925      * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be
926      * accessed by pre-installed holders of a dedicated permission.
927      * <li>
928      * One for cases where the system allowlists the permission when upgrading from an OS version in
929      * which the permission was not restricted to an OS version in which the permission is
930      * restricted. This list corresponds to the
931      * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by
932      * pre-installed holders of a dedicated permission or the installer on record.
933      * <li>
934      * One for cases where the installer of the package allowlists a permission. This list
935      * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be
936      * accessed by pre-installed holders of a dedicated permission or the installer on record.
937      * </ol>
938      *
939      * @param packageName the app for which to get allowlisted permissions
940      * @param allowlistFlag the flag to determine which allowlist to query. Only one flag can be
941      *                      passed.
942      * @return the allowlisted permissions that are on any of the allowlists you query for
943      * @throws SecurityException if you try to access a allowlist that you have no access to
944      *
945      * @see #addAllowlistedRestrictedPermission(String, String, int)
946      * @see #removeAllowlistedRestrictedPermission(String, String, int)
947      * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM
948      * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE
949      * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER
950      *
951      * @hide Pending API
952      */
953     @NonNull
954     @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
955             conditional = true)
getAllowlistedRestrictedPermissions(@onNull String packageName, @PackageManager.PermissionWhitelistFlags int allowlistFlag)956     public Set<String> getAllowlistedRestrictedPermissions(@NonNull String packageName,
957             @PackageManager.PermissionWhitelistFlags int allowlistFlag) {
958         try {
959             final List<String> allowlist = mPermissionManager.getAllowlistedRestrictedPermissions(
960                     packageName, allowlistFlag, mContext.getUserId());
961             if (allowlist == null) {
962                 return Collections.emptySet();
963             }
964             return new ArraySet<>(allowlist);
965         } catch (RemoteException e) {
966             throw e.rethrowFromSystemServer();
967         }
968     }
969 
970     /**
971      * Adds a allowlisted restricted permission for an app.
972      * <p>
973      * Permissions can be hard restricted which means that the app cannot hold them or soft
974      * restricted where the app can hold the permission but in a weaker form. Whether a permission
975      * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or
976      * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission
977      * declaration. Allowlisting a hard restricted permission allows for the to hold that permission
978      * and allowlisting a soft restricted permission allows the app to hold the permission in its
979      * full, unrestricted form.
980      * <p>There are four allowlists:
981      * <ol>
982      * <li>
983      * One for cases where the system permission policy allowlists a permission. This list
984      * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be
985      * accessed by pre-installed holders of a dedicated permission.
986      * <li>
987      * One for cases where the system allowlists the permission when upgrading from an OS version in
988      * which the permission was not restricted to an OS version in which the permission is
989      * restricted. This list corresponds to the
990      * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by
991      * pre-installed holders of a dedicated permission or the installer on record.
992      * <li>
993      * One for cases where the installer of the package allowlists a permission. This list
994      * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be
995      * accessed by pre-installed holders of a dedicated permission or the installer on record.
996      * </ol>
997      * <p>
998      * You need to specify the allowlists for which to set the allowlisted permissions which will
999      * clear the previous allowlisted permissions and replace them with the provided ones.
1000      *
1001      * @param packageName the app for which to get allowlisted permissions
1002      * @param permissionName the allowlisted permission to add
1003      * @param allowlistFlags the allowlists to which to add. Passing multiple flags updates all
1004      *                       specified allowlists.
1005      * @return whether the permission was added to the allowlist
1006      * @throws SecurityException if you try to modify a allowlist that you have no access to.
1007      *
1008      * @see #getAllowlistedRestrictedPermissions(String, int)
1009      * @see #removeAllowlistedRestrictedPermission(String, String, int)
1010      * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM
1011      * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE
1012      * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER
1013      *
1014      * @hide Pending API
1015      */
1016     @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
1017             conditional = true)
addAllowlistedRestrictedPermission(@onNull String packageName, @NonNull String permissionName, @PackageManager.PermissionWhitelistFlags int allowlistFlags)1018     public boolean addAllowlistedRestrictedPermission(@NonNull String packageName,
1019             @NonNull String permissionName,
1020             @PackageManager.PermissionWhitelistFlags int allowlistFlags) {
1021         try {
1022             return mPermissionManager.addAllowlistedRestrictedPermission(packageName,
1023                     permissionName, allowlistFlags, mContext.getUserId());
1024         } catch (RemoteException e) {
1025             throw e.rethrowFromSystemServer();
1026         }
1027     }
1028 
1029     /**
1030      * Removes a allowlisted restricted permission for an app.
1031      * <p>
1032      * Permissions can be hard restricted which means that the app cannot hold them or soft
1033      * restricted where the app can hold the permission but in a weaker form. Whether a permission
1034      * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or
1035      * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission
1036      * declaration. Allowlisting a hard restricted permission allows for the to hold that permission
1037      * and allowlisting a soft restricted permission allows the app to hold the permission in its
1038      * full, unrestricted form.
1039      * <p>There are four allowlists:
1040      * <ol>
1041      * <li>
1042      * One for cases where the system permission policy allowlists a permission. This list
1043      * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be
1044      * accessed by pre-installed holders of a dedicated permission.
1045      * <li>
1046      * One for cases where the system allowlists the permission when upgrading from an OS version in
1047      * which the permission was not restricted to an OS version in which the permission is
1048      * restricted. This list corresponds to the
1049      * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by
1050      * pre-installed holders of a dedicated permission or the installer on record.
1051      * <li>
1052      * One for cases where the installer of the package allowlists a permission. This list
1053      * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be
1054      * accessed by pre-installed holders of a dedicated permission or the installer on record.
1055      * </ol>
1056      * <p>
1057      * You need to specify the allowlists for which to set the allowlisted permissions which will
1058      * clear the previous allowlisted permissions and replace them with the provided ones.
1059      *
1060      * @param packageName the app for which to get allowlisted permissions
1061      * @param permissionName the allowlisted permission to remove
1062      * @param allowlistFlags the allowlists from which to remove. Passing multiple flags updates all
1063      *                       specified allowlists.
1064      * @return whether the permission was removed from the allowlist
1065      * @throws SecurityException if you try to modify a allowlist that you have no access to.
1066      *
1067      * @see #getAllowlistedRestrictedPermissions(String, int)
1068      * @see #addAllowlistedRestrictedPermission(String, String, int)
1069      * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM
1070      * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE
1071      * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER
1072      *
1073      * @hide Pending API
1074      */
1075     @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
1076             conditional = true)
removeAllowlistedRestrictedPermission(@onNull String packageName, @NonNull String permissionName, @PackageManager.PermissionWhitelistFlags int allowlistFlags)1077     public boolean removeAllowlistedRestrictedPermission(@NonNull String packageName,
1078             @NonNull String permissionName,
1079             @PackageManager.PermissionWhitelistFlags int allowlistFlags) {
1080         try {
1081             return mPermissionManager.removeAllowlistedRestrictedPermission(packageName,
1082                     permissionName, allowlistFlags, mContext.getUserId());
1083         } catch (RemoteException e) {
1084             throw e.rethrowFromSystemServer();
1085         }
1086     }
1087 
1088     /**
1089      * Checks whether an application is exempted from having its permissions be automatically
1090      * revoked when the app is unused for an extended period of time.
1091      * <p>
1092      * Only the installer on record that installed the given package, or a holder of
1093      * {@code WHITELIST_AUTO_REVOKE_PERMISSIONS} is allowed to call this.
1094      *
1095      * @param packageName the app for which to set exemption
1096      * @return whether the app is exempted
1097      * @throws SecurityException if you you have no access to this
1098      *
1099      * @see #setAutoRevokeExempted
1100      *
1101      * @hide Pending API
1102      */
1103     @RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS,
1104             conditional = true)
isAutoRevokeExempted(@onNull String packageName)1105     public boolean isAutoRevokeExempted(@NonNull String packageName) {
1106         try {
1107             return mPermissionManager.isAutoRevokeExempted(packageName, mContext.getUserId());
1108         } catch (RemoteException e) {
1109             throw e.rethrowFromSystemServer();
1110         }
1111     }
1112 
1113     /**
1114      * Marks an application exempted from having its permissions be automatically revoked when the
1115      * app is unused for an extended period of time.
1116      * <p>
1117      * Only the installer on record that installed the given package is allowed to call this.
1118      * <p>
1119      * Packages start in exempted state, and it is the installer's responsibility to un-exempt the
1120      * packages it installs, unless auto-revoking permissions from that package would cause
1121      * breakages beyond having to re-request the permission(s).
1122      *
1123      * @param packageName the app for which to set exemption
1124      * @param exempted whether the app should be exempted
1125      * @return whether any change took effect
1126      * @throws SecurityException if you you have no access to modify this
1127      *
1128      * @see #isAutoRevokeExempted
1129      *
1130      * @hide Pending API
1131      */
1132     @RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS,
1133             conditional = true)
setAutoRevokeExempted(@onNull String packageName, boolean exempted)1134     public boolean setAutoRevokeExempted(@NonNull String packageName, boolean exempted) {
1135         try {
1136             return mPermissionManager.setAutoRevokeExempted(packageName, exempted,
1137                     mContext.getUserId());
1138         } catch (RemoteException e) {
1139             throw e.rethrowFromSystemServer();
1140         }
1141     }
1142 
1143     /**
1144      * Get whether you should show UI with rationale for requesting a permission. You should do this
1145      * only if you do not have the permission and the context in which the permission is requested
1146      * does not clearly communicate to the user what would be the benefit from grating this
1147      * permission.
1148      *
1149      * @param permissionName a permission your app wants to request
1150      * @return whether you can show permission rationale UI
1151      *
1152      * @hide
1153      */
1154     //@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
shouldShowRequestPermissionRationale(@onNull String permissionName)1155     public boolean shouldShowRequestPermissionRationale(@NonNull String permissionName) {
1156         try {
1157             final String packageName = mContext.getPackageName();
1158             return mPermissionManager.shouldShowRequestPermissionRationale(packageName,
1159                     permissionName, mContext.getDeviceId(), mContext.getUserId());
1160         } catch (RemoteException e) {
1161             throw e.rethrowFromSystemServer();
1162         }
1163     }
1164 
1165     /**
1166      * Add a listener for permission changes for installed packages.
1167      *
1168      * @param listener the listener to add
1169      *
1170      * @hide
1171      */
1172     //@SystemApi
1173     @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
addOnPermissionsChangeListener( @onNull PackageManager.OnPermissionsChangedListener listener)1174     public void addOnPermissionsChangeListener(
1175             @NonNull PackageManager.OnPermissionsChangedListener listener) {
1176         synchronized (mPermissionListeners) {
1177             if (mPermissionListeners.get(listener) != null) {
1178                 return;
1179             }
1180             final OnPermissionsChangeListenerDelegate delegate =
1181                     new OnPermissionsChangeListenerDelegate(listener, Looper.getMainLooper());
1182             try {
1183                 mPermissionManager.addOnPermissionsChangeListener(delegate);
1184                 mPermissionListeners.put(listener, delegate);
1185             } catch (RemoteException e) {
1186                 throw e.rethrowFromSystemServer();
1187             }
1188         }
1189     }
1190 
1191     /**
1192      * Remove a listener for permission changes for installed packages.
1193      *
1194      * @param listener the listener to remove
1195      *
1196      * @hide
1197      */
1198     //@SystemApi
1199     @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
removeOnPermissionsChangeListener( @onNull PackageManager.OnPermissionsChangedListener listener)1200     public void removeOnPermissionsChangeListener(
1201             @NonNull PackageManager.OnPermissionsChangedListener listener) {
1202         synchronized (mPermissionListeners) {
1203             final IOnPermissionsChangeListener delegate = mPermissionListeners.get(listener);
1204             if (delegate != null) {
1205                 try {
1206                     mPermissionManager.removeOnPermissionsChangeListener(delegate);
1207                     mPermissionListeners.remove(listener);
1208                 } catch (RemoteException e) {
1209                     throw e.rethrowFromSystemServer();
1210                 }
1211             }
1212         }
1213     }
1214 
1215     /**
1216      * Gets the version of the runtime permission database.
1217      *
1218      * @return The database version, -1 when this is an upgrade from pre-Q, 0 when this is a fresh
1219      * install.
1220      *
1221      * @hide
1222      */
1223     @SystemApi
1224     @RequiresPermission(anyOf = {
1225             Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
1226             Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS
1227     })
getRuntimePermissionsVersion()1228     public @IntRange(from = 0) int getRuntimePermissionsVersion() {
1229         try {
1230             return mPackageManager.getRuntimePermissionsVersion(mContext.getUserId());
1231         } catch (RemoteException e) {
1232             throw e.rethrowFromSystemServer();
1233         }
1234     }
1235 
1236     /**
1237      * Sets the version of the runtime permission database.
1238      *
1239      * @param version The new version.
1240      *
1241      * @hide
1242      */
1243     @SystemApi
1244     @RequiresPermission(anyOf = {
1245             Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
1246             Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS
1247     })
setRuntimePermissionsVersion(@ntRangefrom = 0) int version)1248     public void setRuntimePermissionsVersion(@IntRange(from = 0) int version) {
1249         try {
1250             mPackageManager.setRuntimePermissionsVersion(version, mContext.getUserId());
1251         } catch (RemoteException e) {
1252             throw e.rethrowFromSystemServer();
1253         }
1254     }
1255 
1256     /**
1257      * Get set of permissions that have been split into more granular or dependent permissions.
1258      *
1259      * <p>E.g. before {@link android.os.Build.VERSION_CODES#Q} an app that was granted
1260      * {@link Manifest.permission#ACCESS_COARSE_LOCATION} could access the location while it was in
1261      * foreground and background. On platforms after {@link android.os.Build.VERSION_CODES#Q}
1262      * the location permission only grants location access while the app is in foreground. This
1263      * would break apps that target before {@link android.os.Build.VERSION_CODES#Q}. Hence whenever
1264      * such an old app asks for a location permission (i.e. the
1265      * {@link SplitPermissionInfo#getSplitPermission()}), then the
1266      * {@link Manifest.permission#ACCESS_BACKGROUND_LOCATION} permission (inside
1267      * {@link SplitPermissionInfo#getNewPermissions}) is added.
1268      *
1269      * <p>Note: Regular apps do not have to worry about this. The platform and permission controller
1270      * automatically add the new permissions where needed.
1271      *
1272      * @return All permissions that are split.
1273      */
getSplitPermissions()1274     public @NonNull List<SplitPermissionInfo> getSplitPermissions() {
1275         if (mSplitPermissionInfos != null) {
1276             return mSplitPermissionInfos;
1277         }
1278 
1279         List<SplitPermissionInfoParcelable> parcelableList;
1280         try {
1281             parcelableList = ActivityThread.getPermissionManager().getSplitPermissions();
1282         } catch (RemoteException e) {
1283             Slog.e(LOG_TAG, "Error getting split permissions", e);
1284             return Collections.emptyList();
1285         }
1286 
1287         mSplitPermissionInfos = splitPermissionInfoListToNonParcelableList(parcelableList);
1288 
1289         return mSplitPermissionInfos;
1290     }
1291 
1292     /**
1293      * Initialize the PermissionUsageHelper, which will register active app op listeners
1294      *
1295      * @hide
1296      */
initializeUsageHelper()1297     public void initializeUsageHelper() {
1298         if (mUsageHelper == null) {
1299             mUsageHelper = new PermissionUsageHelper(mContext);
1300         }
1301     }
1302 
1303     /**
1304      * Teardown the PermissionUsageHelper, removing listeners
1305      *
1306      * @hide
1307      */
tearDownUsageHelper()1308     public void tearDownUsageHelper() {
1309         if (mUsageHelper != null) {
1310             mUsageHelper.tearDown();
1311             mUsageHelper = null;
1312         }
1313     }
1314 
1315     /**
1316      * @return A list of permission groups currently or recently used by all apps by all users in
1317      * the current profile group.
1318      *
1319      * @hide
1320      */
1321     @TestApi
1322     @NonNull
1323     @RequiresPermission(Manifest.permission.GET_APP_OPS_STATS)
getIndicatorAppOpUsageData()1324     public List<PermissionGroupUsage> getIndicatorAppOpUsageData() {
1325         return getIndicatorAppOpUsageData(new AudioManager().isMicrophoneMute());
1326     }
1327 
1328     /**
1329      * @param micMuted whether to consider the microphone muted when retrieving audio ops
1330      * @return A list of permission groups currently or recently used by all apps by all users in
1331      * the current profile group.
1332      *
1333      * @hide
1334      */
1335     @TestApi
1336     @NonNull
1337     @RequiresPermission(Manifest.permission.GET_APP_OPS_STATS)
getIndicatorAppOpUsageData(boolean micMuted)1338     public List<PermissionGroupUsage> getIndicatorAppOpUsageData(boolean micMuted) {
1339         // Lazily initialize the usage helper
1340         initializeUsageHelper();
1341         boolean includeMicrophoneUsage = !micMuted;
1342         return mUsageHelper.getOpUsageDataByDevice(includeMicrophoneUsage,
1343                 VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT);
1344     }
1345 
1346     /**
1347      * Determine if a package should be shown in indicators. Only a select few roles, and the
1348      * system app itself, are hidden. These values are updated at most every 15 seconds.
1349      * @hide
1350      */
shouldShowPackageForIndicatorCached(@onNull Context context, @NonNull String packageName)1351     public static boolean shouldShowPackageForIndicatorCached(@NonNull Context context,
1352             @NonNull String packageName) {
1353         return !getIndicatorExemptedPackages(context).contains(packageName);
1354     }
1355 
1356     /**
1357      * Get the list of packages that are not shown by the indicators. Only a select few roles, and
1358      * the system app itself, are hidden. These values are updated at most every 15 seconds.
1359      * @hide
1360      */
getIndicatorExemptedPackages(@onNull Context context)1361     public static Set<String> getIndicatorExemptedPackages(@NonNull Context context) {
1362         updateIndicatorExemptedPackages(context);
1363         ArraySet<String> pkgNames = new ArraySet<>();
1364         pkgNames.add(SYSTEM_PKG);
1365         for (int i = 0; i < INDICATOR_EXEMPTED_PACKAGES.length; i++) {
1366             String exemptedPackage = INDICATOR_EXEMPTED_PACKAGES[i];
1367             if (exemptedPackage != null) {
1368                 pkgNames.add(exemptedPackage);
1369             }
1370         }
1371         return pkgNames;
1372     }
1373 
1374     /**
1375      * Update the cached indicator exempted packages
1376      * @hide
1377      */
updateIndicatorExemptedPackages(@onNull Context context)1378     public static void updateIndicatorExemptedPackages(@NonNull Context context) {
1379         long now = SystemClock.elapsedRealtime();
1380         if (sLastIndicatorUpdateTime == -1
1381                 || (now - sLastIndicatorUpdateTime) > EXEMPTED_INDICATOR_ROLE_UPDATE_FREQUENCY_MS) {
1382             sLastIndicatorUpdateTime = now;
1383             for (int i = 0; i < EXEMPTED_ROLES.length; i++) {
1384                 INDICATOR_EXEMPTED_PACKAGES[i] = context.getString(EXEMPTED_ROLES[i]);
1385             }
1386         }
1387     }
1388     /**
1389      * Gets the list of packages that have permissions that specified
1390      * {@code requestDontAutoRevokePermissions=true} in their
1391      * {@code application} manifest declaration.
1392      *
1393      * @return the list of packages for current user
1394      * @hide
1395      */
1396     @SystemApi
1397     @NonNull
1398     @RequiresPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY)
getAutoRevokeExemptionRequestedPackages()1399     public Set<String> getAutoRevokeExemptionRequestedPackages() {
1400         try {
1401             return CollectionUtils.toSet(mPermissionManager.getAutoRevokeExemptionRequestedPackages(
1402                     mContext.getUser().getIdentifier()));
1403         } catch (RemoteException e) {
1404             throw e.rethrowFromSystemServer();
1405         }
1406     }
1407 
1408     /**
1409      * Gets the list of packages that have permissions that specified
1410      * {@code autoRevokePermissions=disallowed} in their
1411      * {@code application} manifest declaration.
1412      *
1413      * @return the list of packages for current user
1414      * @hide
1415      */
1416     @SystemApi
1417     @NonNull
1418     @RequiresPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY)
getAutoRevokeExemptionGrantedPackages()1419     public Set<String> getAutoRevokeExemptionGrantedPackages() {
1420         try {
1421             return CollectionUtils.toSet(mPermissionManager.getAutoRevokeExemptionGrantedPackages(
1422                     mContext.getUser().getIdentifier()));
1423         } catch (RemoteException e) {
1424             throw e.rethrowFromSystemServer();
1425         }
1426     }
1427 
splitPermissionInfoListToNonParcelableList( List<SplitPermissionInfoParcelable> parcelableList)1428     private List<SplitPermissionInfo> splitPermissionInfoListToNonParcelableList(
1429             List<SplitPermissionInfoParcelable> parcelableList) {
1430         final int size = parcelableList.size();
1431         List<SplitPermissionInfo> list = new ArrayList<>(size);
1432         for (int i = 0; i < size; i++) {
1433             list.add(new SplitPermissionInfo(parcelableList.get(i)));
1434         }
1435         return list;
1436     }
1437 
1438     /**
1439      * Converts a {@link List} of {@link SplitPermissionInfo} into a List of
1440      * {@link SplitPermissionInfoParcelable} and returns it.
1441      * @hide
1442      */
splitPermissionInfoListToParcelableList( List<SplitPermissionInfo> splitPermissionsList)1443     public static List<SplitPermissionInfoParcelable> splitPermissionInfoListToParcelableList(
1444             List<SplitPermissionInfo> splitPermissionsList) {
1445         final int size = splitPermissionsList.size();
1446         List<SplitPermissionInfoParcelable> outList = new ArrayList<>(size);
1447         for (int i = 0; i < size; i++) {
1448             SplitPermissionInfo info = splitPermissionsList.get(i);
1449             outList.add(new SplitPermissionInfoParcelable(
1450                     info.getSplitPermission(), info.getNewPermissions(), info.getTargetSdk()));
1451         }
1452         return outList;
1453     }
1454 
1455     /**
1456      * A permission that was added in a previous API level might have split into several
1457      * permissions. This object describes one such split.
1458      */
1459     @Immutable
1460     public static final class SplitPermissionInfo {
1461         private @NonNull final SplitPermissionInfoParcelable mSplitPermissionInfoParcelable;
1462 
1463         @Override
equals(@ullable Object o)1464         public boolean equals(@Nullable Object o) {
1465             if (this == o) return true;
1466             if (o == null || getClass() != o.getClass()) return false;
1467             SplitPermissionInfo that = (SplitPermissionInfo) o;
1468             return mSplitPermissionInfoParcelable.equals(that.mSplitPermissionInfoParcelable);
1469         }
1470 
1471         @Override
hashCode()1472         public int hashCode() {
1473             return mSplitPermissionInfoParcelable.hashCode();
1474         }
1475 
1476         /**
1477          * Get the permission that is split.
1478          */
getSplitPermission()1479         public @NonNull String getSplitPermission() {
1480             return mSplitPermissionInfoParcelable.getSplitPermission();
1481         }
1482 
1483         /**
1484          * Get the permissions that are added.
1485          */
getNewPermissions()1486         public @NonNull List<String> getNewPermissions() {
1487             return mSplitPermissionInfoParcelable.getNewPermissions();
1488         }
1489 
1490         /**
1491          * Get the target API level when the permission was split.
1492          */
getTargetSdk()1493         public int getTargetSdk() {
1494             return mSplitPermissionInfoParcelable.getTargetSdk();
1495         }
1496 
1497         /**
1498          * Constructs a split permission.
1499          *
1500          * @param splitPerm old permission that will be split
1501          * @param newPerms list of new permissions that {@code rootPerm} will be split into
1502          * @param targetSdk apps targetting SDK versions below this will have {@code rootPerm}
1503          * split into {@code newPerms}
1504          * @hide
1505          */
SplitPermissionInfo(@onNull String splitPerm, @NonNull List<String> newPerms, int targetSdk)1506         public SplitPermissionInfo(@NonNull String splitPerm, @NonNull List<String> newPerms,
1507                 int targetSdk) {
1508             this(new SplitPermissionInfoParcelable(splitPerm, newPerms, targetSdk));
1509         }
1510 
SplitPermissionInfo(@onNull SplitPermissionInfoParcelable parcelable)1511         private SplitPermissionInfo(@NonNull SplitPermissionInfoParcelable parcelable) {
1512             mSplitPermissionInfoParcelable = parcelable;
1513         }
1514     }
1515 
1516     /**
1517      * Starts a one-time permission session for a given package.
1518      * @see #startOneTimePermissionSession(String, long, long, int, int)
1519      * @hide
1520      * @deprecated Use {@link #startOneTimePermissionSession(String, long, long, int, int)} instead
1521      */
1522     @Deprecated
1523     @SystemApi
1524     @RequiresPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS)
startOneTimePermissionSession(@onNull String packageName, long timeoutMillis, @ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer, @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive)1525     public void startOneTimePermissionSession(@NonNull String packageName, long timeoutMillis,
1526             @ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer,
1527             @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive) {
1528         startOneTimePermissionSession(packageName, timeoutMillis, -1,
1529                 importanceToResetTimer, importanceToKeepSessionAlive);
1530     }
1531 
1532     /**
1533      * Starts a one-time permission session for a given package. A one-time permission session is
1534      * ended if app becomes inactive. Inactivity is defined as the package's uid importance level
1535      * staying > importanceToResetTimer for timeoutMillis milliseconds. If the package's uid
1536      * importance level goes <= importanceToResetTimer then the timer is reset and doesn't start
1537      * until going > importanceToResetTimer.
1538      * <p>
1539      * When this timeoutMillis is reached if the importance level is <= importanceToKeepSessionAlive
1540      * then the session is extended until either the importance goes above
1541      * importanceToKeepSessionAlive which will end the session or <= importanceToResetTimer which
1542      * will continue the session and reset the timer.
1543      * </p>
1544      * <p>
1545      * Importance levels are defined in {@link android.app.ActivityManager.RunningAppProcessInfo}.
1546      * </p>
1547      * <p>
1548      * Once the session ends
1549      * {@link PermissionControllerService#onOneTimePermissionSessionTimeout(String)} is invoked.
1550      * </p>
1551      * <p>
1552      * Note that if there is currently an active session for a package a new one isn't created but
1553      * each parameter of the existing one will be updated to the more aggressive of both sessions.
1554      * This means that durations will be set to the shortest parameter and importances will be set
1555      * to the lowest one.
1556      * </p>
1557      * @param packageName The package to start a one-time permission session for
1558      * @param timeoutMillis Number of milliseconds for an app to be in an inactive state
1559      * @param revokeAfterKilledDelayMillis Number of milliseconds to wait before revoking on the
1560      *                                     event an app is terminated. Set to -1 to use default
1561      *                                     value for the device.
1562      * @param importanceToResetTimer The least important level to uid must be to reset the timer
1563      * @param importanceToKeepSessionAlive The least important level the uid must be to keep the
1564      *                                     session alive
1565      *
1566      * @hide
1567      */
1568     @SystemApi
1569     @RequiresPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS)
startOneTimePermissionSession(@onNull String packageName, @DurationMillisLong long timeoutMillis, @DurationMillisLong long revokeAfterKilledDelayMillis, @ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer, @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive)1570     public void startOneTimePermissionSession(@NonNull String packageName,
1571             @DurationMillisLong long timeoutMillis,
1572             @DurationMillisLong long revokeAfterKilledDelayMillis,
1573             @ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer,
1574             @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive) {
1575         try {
1576             mPermissionManager.startOneTimePermissionSession(packageName, mContext.getDeviceId(),
1577                     mContext.getUserId(), timeoutMillis, revokeAfterKilledDelayMillis);
1578         } catch (RemoteException e) {
1579             e.rethrowFromSystemServer();
1580         }
1581     }
1582 
1583     /**
1584      * Stops the one-time permission session for the package. The callback to the end of session is
1585      * not invoked. If there is no one-time session for the package then nothing happens.
1586      *
1587      * @param packageName Package to stop the one-time permission session for
1588      *
1589      * @hide
1590      */
1591     @SystemApi
1592     @RequiresPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS)
stopOneTimePermissionSession(@onNull String packageName)1593     public void stopOneTimePermissionSession(@NonNull String packageName) {
1594         try {
1595             mPermissionManager.stopOneTimePermissionSession(packageName,
1596                     mContext.getUserId());
1597         } catch (RemoteException e) {
1598             e.rethrowFromSystemServer();
1599         }
1600     }
1601 
1602     /**
1603      * Checks whether the package with the given pid/uid can read device identifiers.
1604      *
1605      * @param packageName      the name of the package to be checked for identifier access
1606      * @param message          the message to be used for logging during identifier access
1607      *                         verification
1608      * @param callingFeatureId the feature in the package
1609      * @param pid              the process id of the package to be checked
1610      * @param uid              the uid of the package to be checked
1611      * @return {@link PackageManager#PERMISSION_GRANTED} if the package is allowed identifier
1612      * access, {@link PackageManager#PERMISSION_DENIED} otherwise
1613      * @hide
1614      */
1615     @SystemApi
checkDeviceIdentifierAccess(@ullable String packageName, @Nullable String message, @Nullable String callingFeatureId, int pid, int uid)1616     public int checkDeviceIdentifierAccess(@Nullable String packageName, @Nullable String message,
1617             @Nullable String callingFeatureId, int pid, int uid) {
1618         return mLegacyPermissionManager.checkDeviceIdentifierAccess(packageName, message,
1619                 callingFeatureId, pid, uid);
1620     }
1621 
1622     /**
1623      * Registers an attribution source with the OS. An app can only register an attribution
1624      * source for itself. Once an attribution source has been registered another app can
1625      * check whether this registration exists and thus trust the payload in the source
1626      * object. This is important for permission checking and specifically for app op blaming
1627      * since a malicious app should not be able to force the OS to blame another app
1628      * that doesn't participate in an attribution chain.
1629      *
1630      * @param source The attribution source to register.
1631      * @return The registered new attribution source.
1632      *
1633      * @see #isRegisteredAttributionSource(AttributionSource)
1634      *
1635      * @hide
1636      */
1637     @TestApi
registerAttributionSource(@onNull AttributionSource source)1638     public @NonNull AttributionSource registerAttributionSource(@NonNull AttributionSource source) {
1639         // We use a shared static token for sources that are not registered since the token's
1640         // only used for process death detection. If we are about to use the source for security
1641         // enforcement we need to replace the binder with a unique one.
1642         try {
1643             if (serverSideAttributionRegistration()) {
1644                 IBinder newToken = mPermissionManager.registerAttributionSource(source.asState());
1645                 return source.withToken(newToken);
1646             } else {
1647                 AttributionSource registeredSource = source.withToken(new Binder());
1648                 mPermissionManager.registerAttributionSource(registeredSource.asState());
1649                 return registeredSource;
1650             }
1651         } catch (RemoteException e) {
1652             e.rethrowFromSystemServer();
1653         }
1654         return source;
1655     }
1656 
1657     /**
1658      * Checks whether an attribution source is registered.
1659      *
1660      * @param source The attribution source to check.
1661      * @return Whether this is a registered source.
1662      *
1663      * @see #registerAttributionSource(AttributionSource)
1664      *
1665      * @hide
1666      */
1667     @TestApi
1668     @FlaggedApi(FLAG_SHOULD_REGISTER_ATTRIBUTION_SOURCE)
isRegisteredAttributionSource(@onNull AttributionSource source)1669     public boolean isRegisteredAttributionSource(@NonNull AttributionSource source) {
1670         try {
1671             return mPermissionManager.isRegisteredAttributionSource(source.asState());
1672         } catch (RemoteException e) {
1673             e.rethrowFromSystemServer();
1674         }
1675         return false;
1676     }
1677 
1678     /**
1679      * Gets the number of currently registered attribution sources for a particular UID. This should
1680      * only be used for testing purposes.
1681      * @hide
1682      */
1683     @RequiresPermission(Manifest.permission.UPDATE_APP_OPS_STATS)
getRegisteredAttributionSourceCountForTest(int uid)1684     public int getRegisteredAttributionSourceCountForTest(int uid) {
1685         try {
1686             return mPermissionManager.getRegisteredAttributionSourceCount(uid);
1687         } catch (RemoteException e) {
1688             e.rethrowFromSystemServer();
1689         }
1690         return -1;
1691     }
1692 
1693     /**
1694      * Revoke the POST_NOTIFICATIONS permission, without killing the app. This method must ONLY BE
1695      * USED in CTS or local tests.
1696      *
1697      * @param packageName The package to be revoked
1698      * @param userId The user for which to revoke
1699      *
1700      * @hide
1701      */
1702     @TestApi
1703     @RequiresPermission(Manifest.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL)
revokePostNotificationPermissionWithoutKillForTest(@onNull String packageName, int userId)1704     public void revokePostNotificationPermissionWithoutKillForTest(@NonNull String packageName,
1705             int userId) {
1706         try {
1707             mPermissionManager.revokePostNotificationPermissionWithoutKillForTest(packageName,
1708                     userId);
1709         } catch (RemoteException e) {
1710             e.rethrowFromSystemServer();
1711         }
1712     }
1713 
1714     // Only warn once for assuming that root or system UID has a permission
1715     // to reduce duplicate logcat output.
1716     private static volatile boolean sShouldWarnMissingActivityManager = true;
1717 
checkPermissionUncached(@ullable String permission, int pid, int uid, int deviceId)1718     private static int checkPermissionUncached(@Nullable String permission, int pid, int uid,
1719             int deviceId) {
1720         final int appId = UserHandle.getAppId(uid);
1721         if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) {
1722             return PackageManager.PERMISSION_GRANTED;
1723         }
1724         final IActivityManager am = ActivityManager.getService();
1725         if (am == null) {
1726             // We don't have an active ActivityManager instance and the calling UID is not root or
1727             // system, so we don't grant this permission.
1728             Slog.w(LOG_TAG, "Missing ActivityManager; assuming " + uid + " does not hold "
1729                     + permission);
1730             return PackageManager.PERMISSION_DENIED;
1731         }
1732         try {
1733             sShouldWarnMissingActivityManager = true;
1734             return am.checkPermissionForDevice(permission, pid, uid, deviceId);
1735         } catch (RemoteException e) {
1736             throw e.rethrowFromSystemServer();
1737         }
1738     }
1739 
getPermissionRequestStateUncached(String packageName, String permission, int deviceId)1740     private static int getPermissionRequestStateUncached(String packageName, String permission,
1741             int deviceId) {
1742         try {
1743             return AppGlobals.getPermissionManager().getPermissionRequestState(
1744                     packageName, permission, deviceId);
1745         } catch (RemoteException e) {
1746             throw e.rethrowFromSystemServer();
1747         }
1748     }
1749 
1750     /**
1751      * Identifies a permission query.
1752      *
1753      * N.B. we include the checking pid for tracking purposes but don't include it in the equality
1754      * comparison: we use only uid for the actual security check, so comparing pid would result
1755      * in spurious misses.
1756      *
1757      * @hide
1758      */
1759     @Immutable
1760     private static final class PermissionQuery {
1761         final String permission;
1762         final int pid;
1763         final int uid;
1764         final int deviceId;
1765 
PermissionQuery(@ullable String permission, int pid, int uid, int deviceId)1766         PermissionQuery(@Nullable String permission, int pid, int uid, int deviceId) {
1767             this.permission = permission;
1768             this.pid = pid;
1769             this.uid = uid;
1770             this.deviceId = deviceId;
1771         }
1772 
1773         @Override
toString()1774         public String toString() {
1775             return TextUtils.formatSimple("PermissionQuery(permission=\"%s\", pid=%d, uid=%d, "
1776                             + "deviceId=%d)", permission, pid, uid, deviceId);
1777         }
1778 
1779         @Override
hashCode()1780         public int hashCode() {
1781             // N.B. pid doesn't count toward equality and therefore shouldn't count for
1782             // hashing either.
1783             return Objects.hash(permission, uid, deviceId);
1784         }
1785 
1786         @Override
equals(@ullable Object rval)1787         public boolean equals(@Nullable Object rval) {
1788             // N.B. pid doesn't count toward equality!
1789             if (rval == null) {
1790                 return false;
1791             }
1792             PermissionQuery other;
1793             try {
1794                 other = (PermissionQuery) rval;
1795             } catch (ClassCastException ex) {
1796                 return false;
1797             }
1798             return uid == other.uid && deviceId == other.deviceId
1799                     && Objects.equals(permission, other.permission);
1800         }
1801     }
1802 
1803     private static final class PermissionRequestStateQuery {
1804         final String mPackageName;
1805         final String mPermission;
1806         final int mDeviceId;
1807 
PermissionRequestStateQuery(@onNull String packageName, @NonNull String permission, int deviceId)1808         PermissionRequestStateQuery(@NonNull String packageName, @NonNull String permission,
1809                 int deviceId) {
1810             mPackageName = packageName;
1811             mPermission = permission;
1812             mDeviceId = deviceId;
1813         }
1814 
1815         @Override
toString()1816         public String toString() {
1817             return TextUtils.formatSimple("PermissionRequestStateQuery(package=\"%s\","
1818                             + " permission=\"%s\", " + "deviceId=%d)",
1819                     mPackageName, mPermission, mDeviceId);
1820         }
1821 
1822         @Override
hashCode()1823         public int hashCode() {
1824             return Objects.hash(mPackageName, mPermission, mDeviceId);
1825         }
1826 
1827         @Override
equals(@ullable Object rval)1828         public boolean equals(@Nullable Object rval) {
1829             if (rval == null) {
1830                 return false;
1831             }
1832             PermissionRequestStateQuery other;
1833             try {
1834                 other = (PermissionRequestStateQuery) rval;
1835             } catch (ClassCastException ex) {
1836                 return false;
1837             }
1838             return mDeviceId == other.mDeviceId && Objects.equals(mPackageName, other.mPackageName)
1839                     && Objects.equals(mPermission, other.mPermission);
1840         }
1841     }
1842 
1843     // The legacy system property "package_info" had two purposes: to invalidate PIC caches and to
1844     // signal that package information, and therefore permissions, might have changed.
1845     // AudioSystem is the only client of the signaling behavior.  The "separate permissions
1846     // notification" feature splits the two behaviors into two system property names.
1847     //
1848     // If the feature is disabled (legacy behavior) then the two system property names have the
1849     // same value.  This means there is only one system property in use.
1850     //
1851     // If the feature is enabled, then the two system property names have different values, which
1852     // means there is a system property used by PIC and a system property used for signaling.  The
1853     // legacy value is hard-coded in native code that relies on the signaling behavior, so the
1854     // system property name for signaling is the legacy property name, and the system property
1855     // name for PIC is new.
getPackageInfoCacheKey()1856     private static String getPackageInfoCacheKey() {
1857         if (PropertyInvalidatedCache.separatePermissionNotificationsEnabled()) {
1858             return PropertyInvalidatedCache.createSystemCacheKey("package_info_cache");
1859         } else {
1860             return CACHE_KEY_PACKAGE_INFO_NOTIFY;
1861         }
1862     }
1863 
1864     /**
1865      * The system property that is used to notify clients that package information, and therefore
1866      * permissions, may have changed.
1867      * @hide
1868      */
1869     public static final String CACHE_KEY_PACKAGE_INFO_NOTIFY =
1870             PropertyInvalidatedCache.createSystemCacheKey("package_info");
1871 
1872     /**
1873      * The system property that is used to invalidate PIC caches.
1874      * @hide
1875      */
1876     public static final String CACHE_KEY_PACKAGE_INFO_CACHE = getPackageInfoCacheKey();
1877 
1878     /** @hide */
1879     private static final PropertyInvalidatedCache<PermissionQuery, Integer> sPermissionCache =
1880             new PropertyInvalidatedCache<PermissionQuery, Integer>(
1881                     2048, CACHE_KEY_PACKAGE_INFO_CACHE, "checkPermission") {
1882                 @Override
1883                 public Integer recompute(PermissionQuery query) {
1884                     return checkPermissionUncached(query.permission, query.pid, query.uid,
1885                             query.deviceId);
1886                 }
1887             };
1888 
1889     /** @hide */
1890     private static final PropertyInvalidatedCache<PermissionRequestStateQuery, Integer>
1891             sPermissionRequestStateCache =
1892             new PropertyInvalidatedCache<>(
1893                     512, CACHE_KEY_PACKAGE_INFO_CACHE, "getPermissionRequestState") {
1894                 @Override
1895                 public Integer recompute(PermissionRequestStateQuery query) {
1896                     return getPermissionRequestStateUncached(query.mPackageName, query.mPermission,
1897                             query.mDeviceId);
1898                 }
1899             };
1900 
1901     /** @hide */
checkPermission(@ullable String permission, int pid, int uid, int deviceId)1902     public static int checkPermission(@Nullable String permission, int pid, int uid, int deviceId) {
1903         return sPermissionCache.query(new PermissionQuery(permission, pid, uid, deviceId));
1904     }
1905 
1906     /** @hide */
1907     @Context.PermissionRequestState
getPermissionRequestState(@onNull String packageName, @NonNull String permission, int deviceId)1908     public int getPermissionRequestState(@NonNull String packageName, @NonNull String permission,
1909             int deviceId) {
1910         int resolvedDeviceId = resolveDeviceIdForPermissionCheck(mContext, deviceId, permission);
1911         return sPermissionRequestStateCache.query(
1912                 new PermissionRequestStateQuery(packageName, permission, resolvedDeviceId));
1913     }
1914 
1915     /**
1916      * Gets the permission states for requested package and persistent device.
1917      * <p>
1918      * <strong>Note: </strong>Default device permissions are not inherited in this API. Returns the
1919      * exact permission states for the requested device.
1920      *
1921      * @param packageName name of the package you are checking against
1922      * @param persistentDeviceId id of the persistent device you are checking against
1923      * @return mapping of all permission states keyed by their permission names
1924      *
1925      * @hide
1926      */
1927     @SystemApi
1928     @NonNull
1929     @RequiresPermission(anyOf = {
1930             android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
1931             android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
1932             android.Manifest.permission.GET_RUNTIME_PERMISSIONS
1933     })
1934     @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
getAllPermissionStates(@onNull String packageName, @NonNull String persistentDeviceId)1935     public Map<String, PermissionState> getAllPermissionStates(@NonNull String packageName,
1936             @NonNull String persistentDeviceId) {
1937         try {
1938             return mPermissionManager.getAllPermissionStates(packageName, persistentDeviceId,
1939                     mContext.getUserId());
1940         } catch (RemoteException e) {
1941             throw e.rethrowFromSystemServer();
1942         }
1943     }
1944 
1945     /**
1946      * Make checkPermission() above bypass the permission cache in this process.
1947      *
1948      * @hide
1949      */
disablePermissionCache()1950     public static void disablePermissionCache() {
1951         sPermissionCache.disableLocal();
1952     }
1953 
1954     /**
1955      * Like PermissionQuery, but for permission checks based on a package name instead of
1956      * a UID.
1957      */
1958     @Immutable
1959     private static final class PackageNamePermissionQuery {
1960         final String permName;
1961         final String pkgName;
1962         final String persistentDeviceId;
1963         @UserIdInt
1964         final int userId;
1965 
PackageNamePermissionQuery(@ullable String permName, @Nullable String pkgName, @Nullable String persistentDeviceId, @UserIdInt int userId)1966         PackageNamePermissionQuery(@Nullable String permName, @Nullable String pkgName,
1967                 @Nullable String persistentDeviceId, @UserIdInt int userId) {
1968             this.permName = permName;
1969             this.pkgName = pkgName;
1970             this.persistentDeviceId = persistentDeviceId;
1971             this.userId = userId;
1972         }
1973 
1974         @Override
toString()1975         public String toString() {
1976             return TextUtils.formatSimple(
1977                     "PackageNamePermissionQuery(pkgName=\"%s\", permName=\"%s\", "
1978                             + "persistentDeviceId=%s, userId=%s\")",
1979                     pkgName, permName, persistentDeviceId, userId);
1980         }
1981 
1982         @Override
hashCode()1983         public int hashCode() {
1984             return Objects.hash(permName, pkgName, persistentDeviceId, userId);
1985         }
1986 
1987         @Override
equals(@ullable Object rval)1988         public boolean equals(@Nullable Object rval) {
1989             if (rval == null) {
1990                 return false;
1991             }
1992             PackageNamePermissionQuery other;
1993             try {
1994                 other = (PackageNamePermissionQuery) rval;
1995             } catch (ClassCastException ex) {
1996                 return false;
1997             }
1998             return Objects.equals(permName, other.permName)
1999                     && Objects.equals(pkgName, other.pkgName)
2000                     && Objects.equals(persistentDeviceId, other.persistentDeviceId)
2001                     && userId == other.userId;
2002         }
2003     }
2004 
2005     /* @hide */
checkPackageNamePermissionUncached( String permName, String pkgName, String persistentDeviceId, @UserIdInt int userId)2006     private static int checkPackageNamePermissionUncached(
2007             String permName, String pkgName, String persistentDeviceId, @UserIdInt int userId) {
2008         try {
2009             return ActivityThread.getPermissionManager().checkPermission(
2010                     pkgName, permName, persistentDeviceId, userId);
2011         } catch (RemoteException e) {
2012             throw e.rethrowFromSystemServer();
2013         }
2014     }
2015 
2016     /* @hide */
2017     private static PropertyInvalidatedCache<PackageNamePermissionQuery, Integer>
2018             sPackageNamePermissionCache =
2019             new PropertyInvalidatedCache<PackageNamePermissionQuery, Integer>(
2020                     16, CACHE_KEY_PACKAGE_INFO_CACHE, "checkPackageNamePermission") {
2021                 @Override
2022                 public Integer recompute(PackageNamePermissionQuery query) {
2023                     return checkPackageNamePermissionUncached(
2024                             query.permName, query.pkgName, query.persistentDeviceId, query.userId);
2025                 }
2026                 @Override
2027                 public boolean bypass(PackageNamePermissionQuery query) {
2028                     return query.userId < 0;
2029                 }
2030             };
2031 
2032     /**
2033      * Check whether a package has a permission for given device.
2034      *
2035      * @hide
2036      */
checkPackageNamePermission(String permName, String pkgName, int deviceId, @UserIdInt int userId)2037     public int checkPackageNamePermission(String permName, String pkgName,
2038             int deviceId, @UserIdInt int userId) {
2039         int resolvedDeviceId = resolveDeviceIdForPermissionCheck(mContext, deviceId, permName);
2040         String persistentDeviceId = getPersistentDeviceId(resolvedDeviceId);
2041         return sPackageNamePermissionCache.query(
2042                 new PackageNamePermissionQuery(permName, pkgName, persistentDeviceId, userId));
2043     }
2044 
2045     /**
2046      * When checking a device-aware permission on a remote device, if the permission is CAMERA
2047      * or RECORD_AUDIO we need to check remote device's corresponding capability. If the remote
2048      * device doesn't have capability fall back to checking permission on the default device.
2049      *
2050      * @hide
2051      */
resolveDeviceIdForPermissionCheck(@onNull Context context, int deviceId, @Nullable String permission)2052     public static int resolveDeviceIdForPermissionCheck(@NonNull Context context, int deviceId,
2053             @Nullable String permission) {
2054         if (deviceId == Context.DEVICE_ID_DEFAULT || !DEVICE_AWARE_PERMISSIONS.contains(
2055                 permission)) {
2056             return Context.DEVICE_ID_DEFAULT;
2057         }
2058 
2059         VirtualDeviceManager virtualDeviceManager =
2060                 context.getSystemService(VirtualDeviceManager.class);
2061         if (virtualDeviceManager == null) {
2062             Slog.e(LOG_TAG, "VDM is not enabled when device id is not default. deviceId = "
2063                     + deviceId);
2064         } else {
2065             VirtualDevice virtualDevice = virtualDeviceManager.getVirtualDevice(deviceId);
2066             if (virtualDevice != null) {
2067                 if ((Objects.equals(permission, Manifest.permission.RECORD_AUDIO)
2068                         && !virtualDevice.hasCustomAudioInputSupport())
2069                         || (Objects.equals(permission, Manifest.permission.CAMERA)
2070                         && !virtualDevice.hasCustomCameraSupport())) {
2071                     deviceId = Context.DEVICE_ID_DEFAULT;
2072                 }
2073             } else {
2074                 Slog.e(LOG_TAG,
2075                         "virtualDevice is not found when device id is not default. deviceId = "
2076                                 + deviceId);
2077             }
2078         }
2079         return deviceId;
2080     }
2081 
2082     @Nullable
getPersistentDeviceId(int deviceId)2083     private String getPersistentDeviceId(int deviceId) {
2084         String persistentDeviceId = null;
2085 
2086         if (deviceId == Context.DEVICE_ID_DEFAULT) {
2087             persistentDeviceId = PERSISTENT_DEVICE_ID_DEFAULT;
2088         } else {
2089             VirtualDeviceManager virtualDeviceManager = mContext.getSystemService(
2090                     VirtualDeviceManager.class);
2091             if (virtualDeviceManager != null) {
2092                 VirtualDevice virtualDevice = virtualDeviceManager.getVirtualDevice(deviceId);
2093                 if (virtualDevice == null) {
2094                     Slog.e(LOG_TAG, "Virtual device is not found with device Id " + deviceId);
2095                     return null;
2096                 }
2097                 persistentDeviceId = virtualDevice.getPersistentDeviceId();
2098                 if (persistentDeviceId == null) {
2099                     Slog.e(LOG_TAG, "Cannot find persistent device Id for " + deviceId);
2100                 }
2101             }
2102         }
2103         return persistentDeviceId;
2104     }
2105 
2106     /**
2107      * Check whether a package has been granted a permission on a given device.
2108      * <p>
2109      * <strong>Note: </strong>This API returns the underlying permission state
2110      * as-is and is mostly intended for permission managing system apps. To
2111      * perform an access check for a certain app, please use the
2112      * {@link Context#checkPermission} APIs instead.
2113      *
2114      * @param permissionName The name of the permission you are checking for.
2115      * @param packageName The name of the package you are checking against.
2116      * @param persistentDeviceId The id of the physical device that you are checking permission
2117      *                           against.
2118      *
2119      * @return If the package has the permission on the device, PERMISSION_GRANTED is
2120      * returned.  If it does not have the permission on the device, PERMISSION_DENIED
2121      * is returned.
2122      *
2123      * @see VirtualDevice#getPersistentDeviceId()
2124      * @see PackageManager#PERMISSION_GRANTED
2125      * @see PackageManager#PERMISSION_DENIED
2126      *
2127      * @hide
2128      */
2129     @SystemApi
2130     @PermissionResult
2131     @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
checkPermission(@onNull String permissionName, @NonNull String packageName, @NonNull String persistentDeviceId)2132     public int checkPermission(@NonNull String permissionName, @NonNull String packageName,
2133             @NonNull String persistentDeviceId) {
2134         return sPackageNamePermissionCache.query(
2135                 new PackageNamePermissionQuery(permissionName, packageName, persistentDeviceId,
2136                         mContext.getUserId()));
2137     }
2138 
2139     /**
2140      * Make checkPackageNamePermission() bypass the cache in this process.
2141      *
2142      * @hide
2143      */
disablePackageNamePermissionCache()2144     public static void disablePackageNamePermissionCache() {
2145         sPackageNamePermissionCache.disableLocal();
2146     }
2147 
2148     private final class OnPermissionsChangeListenerDelegate
2149             extends IOnPermissionsChangeListener.Stub implements Handler.Callback {
2150         private static final int MSG_PERMISSIONS_CHANGED = 1;
2151 
2152         private final PackageManager.OnPermissionsChangedListener mListener;
2153         private final Handler mHandler;
2154 
OnPermissionsChangeListenerDelegate( PackageManager.OnPermissionsChangedListener listener, Looper looper)2155         public OnPermissionsChangeListenerDelegate(
2156                 PackageManager.OnPermissionsChangedListener listener, Looper looper) {
2157             mListener = listener;
2158             mHandler = new Handler(looper, this);
2159         }
2160 
2161         @Override
onPermissionsChanged(int uid, String persistentDeviceId)2162         public void onPermissionsChanged(int uid, String persistentDeviceId) {
2163             mHandler.obtainMessage(MSG_PERMISSIONS_CHANGED, uid, 0, persistentDeviceId)
2164                     .sendToTarget();
2165         }
2166 
2167         @Override
handleMessage(Message msg)2168         public boolean handleMessage(Message msg) {
2169             switch (msg.what) {
2170                 case MSG_PERMISSIONS_CHANGED: {
2171                     final int uid = msg.arg1;
2172                     final String persistentDeviceId = msg.obj.toString();
2173                     mListener.onPermissionsChanged(uid, persistentDeviceId);
2174                     return true;
2175                 }
2176                 default:
2177                     return false;
2178             }
2179         }
2180     }
2181 
2182     /**
2183      * Data class for the state of a permission requested by a package
2184      *
2185      * @hide
2186      */
2187     @SystemApi
2188     @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
2189     public static final class PermissionState implements Parcelable {
2190         private final boolean mGranted;
2191         private final int mFlags;
2192 
2193         /** @hide */
2194         @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
PermissionState(boolean granted, int flags)2195         public PermissionState(boolean granted, int flags) {
2196             mGranted = granted;
2197             mFlags = flags;
2198         }
2199 
2200         /**
2201          * Returns whether this permission is granted
2202          */
2203         @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
isGranted()2204         public boolean isGranted() {
2205             return mGranted;
2206         }
2207 
2208         /**
2209          * Returns the flags associated with this permission state
2210          * @see PackageManager#getPermissionFlags
2211          */
2212         @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
getFlags()2213         public int getFlags() {
2214             return mFlags;
2215         }
2216 
2217         @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
2218         @Override
describeContents()2219         public int describeContents() {
2220             return 0;
2221         }
2222 
2223         @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
2224         @Override
writeToParcel(@onNull Parcel parcel, int flags)2225         public void writeToParcel(@NonNull Parcel parcel, int flags) {
2226             parcel.writeBoolean(mGranted);
2227             parcel.writeInt(mFlags);
2228         }
2229 
PermissionState(Parcel parcel)2230         private PermissionState(Parcel parcel) {
2231             this(parcel.readBoolean(), parcel.readInt());
2232         }
2233 
2234         @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
2235         public static final @NonNull Creator<PermissionState> CREATOR = new Creator<>() {
2236             public PermissionState createFromParcel(Parcel source) {
2237                 return new PermissionState(source);
2238             }
2239 
2240             public PermissionState[] newArray(int size) {
2241                 return new PermissionState[size];
2242             }
2243         };
2244 
2245         /** @hide */
2246         @Override
equals(Object o)2247         public boolean equals(Object o) {
2248             if (this == o) return true;
2249             if (o == null || getClass() != o.getClass()) return false;
2250             PermissionState that = (PermissionState) o;
2251             return mGranted == that.mGranted && mFlags == that.mFlags;
2252         }
2253 
2254         /** @hide */
2255         @Override
hashCode()2256         public int hashCode() {
2257             return Objects.hash(mGranted, mFlags);
2258         }
2259 
2260         /** @hide */
2261         @Override
toString()2262         public String toString() {
2263             return "PermissionState{"
2264                     + "mGranted=" + mGranted
2265                     + ", mFlags=" + mFlags
2266                     + '}';
2267         }
2268     }
2269 }
2270