• 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.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
20 import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE;
21 import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
22 import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
23 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
24 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
25 import static android.os.Build.VERSION_CODES.S;
26 
27 import android.Manifest;
28 import android.annotation.CheckResult;
29 import android.annotation.DurationMillisLong;
30 import android.annotation.IntRange;
31 import android.annotation.NonNull;
32 import android.annotation.Nullable;
33 import android.annotation.RequiresPermission;
34 import android.annotation.SdkConstant;
35 import android.annotation.SdkConstant.SdkConstantType;
36 import android.annotation.SystemApi;
37 import android.annotation.SystemService;
38 import android.annotation.TestApi;
39 import android.annotation.UserIdInt;
40 import android.app.ActivityManager;
41 import android.app.ActivityThread;
42 import android.app.AppGlobals;
43 import android.app.AppOpsManager;
44 import android.app.IActivityManager;
45 import android.app.PropertyInvalidatedCache;
46 import android.compat.annotation.ChangeId;
47 import android.compat.annotation.EnabledAfter;
48 import android.content.AttributionSource;
49 import android.content.Context;
50 import android.content.PermissionChecker;
51 import android.content.pm.IPackageManager;
52 import android.content.pm.PackageManager;
53 import android.content.pm.ParceledListSlice;
54 import android.content.pm.PermissionGroupInfo;
55 import android.content.pm.PermissionInfo;
56 import android.content.pm.permission.SplitPermissionInfoParcelable;
57 import android.media.AudioManager;
58 import android.os.Binder;
59 import android.os.Build;
60 import android.os.Handler;
61 import android.os.Looper;
62 import android.os.Message;
63 import android.os.Process;
64 import android.os.RemoteException;
65 import android.os.ServiceManager;
66 import android.os.SystemClock;
67 import android.os.UserHandle;
68 import android.util.ArrayMap;
69 import android.util.ArraySet;
70 import android.util.DebugUtils;
71 import android.util.Log;
72 import android.util.Slog;
73 
74 import com.android.internal.R;
75 import com.android.internal.annotations.Immutable;
76 import com.android.internal.util.CollectionUtils;
77 
78 import java.util.ArrayList;
79 import java.util.Collections;
80 import java.util.List;
81 import java.util.Objects;
82 import java.util.Set;
83 
84 /**
85  * System level service for accessing the permission capabilities of the platform.
86  *
87  * @hide
88  */
89 @SystemApi
90 @SystemService(Context.PERMISSION_SERVICE)
91 public final class PermissionManager {
92     private static final String LOG_TAG = PermissionManager.class.getName();
93 
94     /**
95      * The permission is granted.
96      */
97     public static final int PERMISSION_GRANTED = 0;
98 
99     /**
100      * The permission is denied. Applicable only to runtime and app op permissions.
101      * <p>
102      * The app isn't expecting the permission to be denied so that a "no-op" action should be taken,
103      * such as returning an empty result.
104      */
105     public static final int PERMISSION_SOFT_DENIED = 1;
106 
107     /**
108      * The permission is denied.
109      * <p>
110      * The app should receive a {@code SecurityException}, or an error through a relevant callback.
111      */
112     public static final int PERMISSION_HARD_DENIED = 2;
113 
114     /**
115      * The set of flags that indicate that a permission state has been explicitly set
116      *
117      * @hide
118      */
119     public static final int EXPLICIT_SET_FLAGS = FLAG_PERMISSION_USER_SET
120             | FLAG_PERMISSION_USER_FIXED | FLAG_PERMISSION_POLICY_FIXED
121             | FLAG_PERMISSION_SYSTEM_FIXED | FLAG_PERMISSION_GRANTED_BY_DEFAULT
122             | FLAG_PERMISSION_GRANTED_BY_ROLE;
123 
124     /**
125      * Activity action: Launch UI to review permission decisions.
126      * <p>
127      * <strong>Important:</strong>You must protect the activity that handles this action with the
128      * {@link android.Manifest.permission#START_REVIEW_PERMISSION_DECISIONS} permission to ensure
129      * that only the system can launch this activity. The system will not launch activities that are
130      * not properly protected.
131      * <p>
132      * Input: Nothing.
133      * </p>
134      * <p>
135      * Output: Nothing.
136      * </p>
137      */
138     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
139     @RequiresPermission(android.Manifest.permission.START_REVIEW_PERMISSION_DECISIONS)
140     public static final String ACTION_REVIEW_PERMISSION_DECISIONS =
141             "android.permission.action.REVIEW_PERMISSION_DECISIONS";
142 
143 
144     /** @hide */
145     public static final String LOG_TAG_TRACE_GRANTS = "PermissionGrantTrace";
146 
147     /** @hide */
148     public static final String KILL_APP_REASON_PERMISSIONS_REVOKED =
149             "permissions revoked";
150     /** @hide */
151     public static final String KILL_APP_REASON_GIDS_CHANGED =
152             "permission grant or revoke changed gids";
153 
154     private static final String SYSTEM_PKG = "android";
155 
156     /**
157      * Refuse to install package if groups of permissions are bad
158      * - Permission groups should only be shared between apps sharing a certificate
159      * - If a permission belongs to a group that group should be defined
160      *
161      * @hide
162      */
163     @ChangeId
164     @EnabledAfter(targetSdkVersion = S)
165     public static final long CANNOT_INSTALL_WITH_BAD_PERMISSION_GROUPS = 146211400;
166 
167     /**
168      * The time to wait in between refreshing the exempted indicator role packages
169      */
170     private static final long EXEMPTED_INDICATOR_ROLE_UPDATE_FREQUENCY_MS = 15000;
171 
172     private static long sLastIndicatorUpdateTime = -1;
173 
174     private static final int[] EXEMPTED_ROLES = {R.string.config_systemAmbientAudioIntelligence,
175         R.string.config_systemUiIntelligence, R.string.config_systemAudioIntelligence,
176         R.string.config_systemNotificationIntelligence, R.string.config_systemTextIntelligence,
177         R.string.config_systemVisualIntelligence};
178 
179     private static final String[] INDICATOR_EXEMPTED_PACKAGES = new String[EXEMPTED_ROLES.length];
180 
181     /**
182      * Note: Changing this won't do anything on its own - you should also change the filtering in
183      * {@link #shouldTraceGrant}.
184      *
185      * See log output for tag {@link #LOG_TAG_TRACE_GRANTS}
186      *
187      * @hide
188      */
189     public static final boolean DEBUG_TRACE_GRANTS = false;
190     /**
191      * @hide
192      */
193     public static final boolean DEBUG_TRACE_PERMISSION_UPDATES = false;
194 
195     /**
196      * Intent extra: List of PermissionGroupUsages
197      * <p>
198      * Type: {@code List<PermissionGroupUsage>}
199      * </p>
200      * @hide
201      */
202     @SystemApi
203     public static final String EXTRA_PERMISSION_USAGES =
204             "android.permission.extra.PERMISSION_USAGES";
205 
206     private final @NonNull Context mContext;
207 
208     private final IPackageManager mPackageManager;
209 
210     private final IPermissionManager mPermissionManager;
211 
212     private final LegacyPermissionManager mLegacyPermissionManager;
213 
214     private final ArrayMap<PackageManager.OnPermissionsChangedListener,
215             IOnPermissionsChangeListener> mPermissionListeners = new ArrayMap<>();
216     private PermissionUsageHelper mUsageHelper;
217 
218     private List<SplitPermissionInfo> mSplitPermissionInfos;
219 
220     /**
221      * Creates a new instance.
222      *
223      * @param context The current context in which to operate
224      *
225      * @hide
226      */
PermissionManager(@onNull Context context)227     public PermissionManager(@NonNull Context context)
228             throws ServiceManager.ServiceNotFoundException {
229         mContext = context;
230         mPackageManager = AppGlobals.getPackageManager();
231         mPermissionManager = IPermissionManager.Stub.asInterface(ServiceManager.getServiceOrThrow(
232                 "permissionmgr"));
233         mLegacyPermissionManager = context.getSystemService(LegacyPermissionManager.class);
234     }
235 
236     /**
237      * Checks whether a given data access chain described by the given {@link AttributionSource}
238      * has a given permission.
239      *
240      * <strong>NOTE:</strong> Use this method only for permission checks at the
241      * point where you will deliver the permission protected data to clients.
242      *
243      * <p>For example, if an app registers a location listener it should have the location
244      * permission but no data is actually sent to the app at the moment of registration
245      * and you should use {@link #checkPermissionForPreflight(String, AttributionSource)}
246      * to determine if the app has or may have location permission (if app has only foreground
247      * location the grant state depends on the app's fg/gb state) and this check will not
248      * leave a trace that permission protected data was delivered. When you are about to
249      * deliver the location data to a registered listener you should use this method which
250      * will evaluate the permission access based on the current fg/bg state of the app and
251      * leave a record that the data was accessed.
252      *
253      * <p>Requires the start of the AttributionSource chain to have the UPDATE_APP_OPS_STATS
254      * permission for the app op accesses to be given the TRUSTED_PROXY/PROXIED flags, otherwise the
255      * accesses will have the UNTRUSTED flags.
256      *
257      * @param permission The permission to check.
258      * @param attributionSource the permission identity
259      * @param message A message describing the reason the permission was checked
260      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
261      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
262      *
263      * @see #checkPermissionForPreflight(String, AttributionSource)
264      */
265     @PermissionCheckerManager.PermissionResult
266     @RequiresPermission(value = Manifest.permission.UPDATE_APP_OPS_STATS, conditional = true)
checkPermissionForDataDelivery(@onNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message)267     public int checkPermissionForDataDelivery(@NonNull String permission,
268             @NonNull AttributionSource attributionSource, @Nullable String message) {
269         return PermissionChecker.checkPermissionForDataDelivery(mContext, permission,
270                 // FIXME(b/199526514): PID should be passed inside AttributionSource.
271                 PermissionChecker.PID_UNKNOWN, attributionSource, message);
272     }
273 
274     /**
275      *
276      * Similar to checkPermissionForDataDelivery, except it results in an app op start, rather than
277      * a note. If this method is used, then {@link #finishDataDelivery(String, AttributionSource)}
278      * must be used when access is finished.
279      *
280      * @param permission The permission to check.
281      * @param attributionSource the permission identity
282      * @param message A message describing the reason the permission was checked
283      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
284      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
285      *
286      * <p>Requires the start of the AttributionSource chain to have the UPDATE_APP_OPS_STATS
287      * permission for the app op accesses to be given the TRUSTED_PROXY/PROXIED flags, otherwise the
288      * accesses will have the UNTRUSTED flags.
289      *
290      * @see #checkPermissionForDataDelivery(String, AttributionSource, String)
291      */
292     @PermissionCheckerManager.PermissionResult
293     @RequiresPermission(value = Manifest.permission.UPDATE_APP_OPS_STATS, conditional = true)
checkPermissionForStartDataDelivery(@onNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message)294     public int checkPermissionForStartDataDelivery(@NonNull String permission,
295             @NonNull AttributionSource attributionSource, @Nullable String message) {
296         return PermissionChecker.checkPermissionForDataDelivery(mContext, permission,
297                 // FIXME(b/199526514): PID should be passed inside AttributionSource.
298                 PermissionChecker.PID_UNKNOWN, attributionSource, message, true);
299     }
300 
301     /**
302      * Indicate that usage has finished for an {@link AttributionSource} started with
303      * {@link #checkPermissionForStartDataDelivery(String, AttributionSource, String)}
304      *
305      * @param permission The permission to check.
306      * @param attributionSource the permission identity to finish
307      */
finishDataDelivery(@onNull String permission, @NonNull AttributionSource attributionSource)308     public void finishDataDelivery(@NonNull String permission,
309             @NonNull AttributionSource attributionSource) {
310         PermissionChecker.finishDataDelivery(mContext, AppOpsManager.permissionToOp(permission),
311                 attributionSource);
312     }
313 
314     /**
315      * Checks whether a given data access chain described by the given {@link AttributionSource}
316      * has a given permission. Call this method if you are the datasource which would not blame you
317      * for access to the data since you are the data. Use this API if you are the datasource of the
318      * protected state.
319      *
320      * <strong>NOTE:</strong> Use this method only for permission checks at the
321      * point where you will deliver the permission protected data to clients.
322      *
323      * <p>For example, if an app registers a location listener it should have the location
324      * permission but no data is actually sent to the app at the moment of registration
325      * and you should use {@link #checkPermissionForPreflight(String, AttributionSource)}
326      * to determine if the app has or may have location permission (if app has only foreground
327      * location the grant state depends on the app's fg/gb state) and this check will not
328      * leave a trace that permission protected data was delivered. When you are about to
329      * deliver the location data to a registered listener you should use this method which
330      * will evaluate the permission access based on the current fg/bg state of the app and
331      * leave a record that the data was accessed.
332      *
333      * <p>Requires the start of the AttributionSource chain to have the UPDATE_APP_OPS_STATS
334      * permission for the app op accesses to be given the TRUSTED_PROXY/PROXIED flags, otherwise the
335      * accesses will have the UNTRUSTED flags.
336      *
337      * @param permission The permission to check.
338      * @param attributionSource the permission identity
339      * @param message A message describing the reason the permission was checked
340      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
341      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
342      *
343      * @see #checkPermissionForPreflight(String, AttributionSource)
344      */
345     @PermissionCheckerManager.PermissionResult
346     @RequiresPermission(value = Manifest.permission.UPDATE_APP_OPS_STATS, conditional = true)
checkPermissionForDataDeliveryFromDataSource(@onNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message)347     public int checkPermissionForDataDeliveryFromDataSource(@NonNull String permission,
348             @NonNull AttributionSource attributionSource, @Nullable String message) {
349         return PermissionChecker.checkPermissionForDataDeliveryFromDataSource(mContext, permission,
350                 PermissionChecker.PID_UNKNOWN, attributionSource, message);
351     }
352 
353     /**
354      * Checks whether a given data access chain described by the given {@link AttributionSource}
355      * has a given permission.
356      *
357      * <strong>NOTE:</strong> Use this method only for permission checks at the
358      * preflight point where you will not deliver the permission protected data
359      * to clients but schedule permission data delivery, apps register listeners,
360      * etc.
361      *
362      * <p>For example, if an app registers a data listener it should have the required
363      * permission but no data is actually sent to the app at the moment of registration
364      * and you should use this method to determine if the app has or may have the
365      * permission and this check will not leave a trace that permission protected data
366      * was delivered. When you are about to deliver the protected data to a registered
367      * listener you should use {@link #checkPermissionForDataDelivery(String,
368      * AttributionSource, String)} which will evaluate the permission access based
369      * on the current fg/bg state of the app and leave a record that the data was accessed.
370      *
371      * @param permission The permission to check.
372      * @param attributionSource The identity for which to check the permission.
373      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
374      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
375      */
376     @PermissionCheckerManager.PermissionResult
checkPermissionForPreflight(@onNull String permission, @NonNull AttributionSource attributionSource)377     public int checkPermissionForPreflight(@NonNull String permission,
378             @NonNull AttributionSource attributionSource) {
379         return PermissionChecker.checkPermissionForPreflight(mContext, permission,
380                 attributionSource);
381     }
382 
383     /**
384      * Retrieve all of the information we know about a particular permission.
385      *
386      * @param permissionName the fully qualified name (e.g. com.android.permission.LOGIN) of the
387      *                       permission you are interested in
388      * @param flags additional option flags to modify the data returned
389      * @return a {@link PermissionInfo} containing information about the permission, or {@code null}
390      *         if not found
391      *
392      * @hide Pending API
393      */
394     @Nullable
getPermissionInfo(@onNull String permissionName, @PackageManager.PermissionInfoFlags int flags)395     public PermissionInfo getPermissionInfo(@NonNull String permissionName,
396             @PackageManager.PermissionInfoFlags int flags) {
397         try {
398             final String packageName = mContext.getOpPackageName();
399             return mPermissionManager.getPermissionInfo(permissionName, packageName, flags);
400         } catch (RemoteException e) {
401             throw e.rethrowFromSystemServer();
402         }
403     }
404 
405     /**
406      * Query for all of the permissions associated with a particular group.
407      *
408      * @param groupName the fully qualified name (e.g. com.android.permission.LOGIN) of the
409      *                  permission group you are interested in. Use {@code null} to find all of the
410      *                  permissions not associated with a group
411      * @param flags additional option flags to modify the data returned
412      * @return a list of {@link PermissionInfo} containing information about all of the permissions
413      *         in the given group, or {@code null} if the group is not found
414      *
415      * @hide Pending API
416      */
417     @Nullable
queryPermissionsByGroup(@ullable String groupName, @PackageManager.PermissionInfoFlags int flags)418     public List<PermissionInfo> queryPermissionsByGroup(@Nullable String groupName,
419             @PackageManager.PermissionInfoFlags int flags) {
420         try {
421             final ParceledListSlice<PermissionInfo> parceledList =
422                     mPermissionManager.queryPermissionsByGroup(groupName, flags);
423             if (parceledList == null) {
424                 return null;
425             }
426             return parceledList.getList();
427         } catch (RemoteException e) {
428             throw e.rethrowFromSystemServer();
429         }
430     }
431 
432     /**
433      * Add a new dynamic permission to the system. For this to work, your package must have defined
434      * a permission tree through the
435      * {@link android.R.styleable#AndroidManifestPermissionTree &lt;permission-tree&gt;} tag in its
436      * manifest. A package can only add permissions to trees that were defined by either its own
437      * package or another with the same user id; a permission is in a tree if it matches the name of
438      * the permission tree + ".": for example, "com.foo.bar" is a member of the permission tree
439      * "com.foo".
440      * <p>
441      * It is good to make your permission tree name descriptive, because you are taking possession
442      * of that entire set of permission names. Thus, it must be under a domain you control, with a
443      * suffix that will not match any normal permissions that may be declared in any applications
444      * that are part of that domain.
445      * <p>
446      * New permissions must be added before any .apks are installed that use those permissions.
447      * Permissions you add through this method are remembered across reboots of the device. If the
448      * given permission already exists, the info you supply here will be used to update it.
449      *
450      * @param permissionInfo description of the permission to be added
451      * @param async whether the persistence of the permission should be asynchronous, allowing it to
452      *              return quicker and batch a series of adds, at the expense of no guarantee the
453      *              added permission will be retained if the device is rebooted before it is
454      *              written.
455      * @return {@code true} if a new permission was created, {@code false} if an existing one was
456      *         updated
457      * @throws SecurityException if you are not allowed to add the given permission name
458      *
459      * @see #removePermission(String)
460      *
461      * @hide Pending API
462      */
addPermission(@onNull PermissionInfo permissionInfo, boolean async)463     public boolean addPermission(@NonNull PermissionInfo permissionInfo, boolean async) {
464         try {
465             return mPermissionManager.addPermission(permissionInfo, async);
466         } catch (RemoteException e) {
467             throw e.rethrowFromSystemServer();
468         }
469     }
470 
471     /**
472      * Removes a permission that was previously added with
473      * {@link #addPermission(PermissionInfo, boolean)}. The same ownership rules apply -- you are
474      * only allowed to remove permissions that you are allowed to add.
475      *
476      * @param permissionName the name of the permission to remove
477      * @throws SecurityException if you are not allowed to remove the given permission name
478      *
479      * @see #addPermission(PermissionInfo, boolean)
480      *
481      * @hide Pending API
482      */
removePermission(@onNull String permissionName)483     public void removePermission(@NonNull String permissionName) {
484         try {
485             mPermissionManager.removePermission(permissionName);
486         } catch (RemoteException e) {
487             throw e.rethrowFromSystemServer();
488         }
489     }
490 
491     /**
492      * Retrieve all of the information we know about a particular group of permissions.
493      *
494      * @param groupName the fully qualified name (e.g. com.android.permission_group.APPS) of the
495      *                  permission you are interested in
496      * @param flags additional option flags to modify the data returned
497      * @return a {@link PermissionGroupInfo} containing information about the permission, or
498      *         {@code null} if not found
499      *
500      * @hide Pending API
501      */
502     @Nullable
getPermissionGroupInfo(@onNull String groupName, @PackageManager.PermissionGroupInfoFlags int flags)503     public PermissionGroupInfo getPermissionGroupInfo(@NonNull String groupName,
504             @PackageManager.PermissionGroupInfoFlags int flags) {
505         try {
506             return mPermissionManager.getPermissionGroupInfo(groupName, flags);
507         } catch (RemoteException e) {
508             throw e.rethrowFromSystemServer();
509         }
510     }
511 
512     /**
513      * Retrieve all of the known permission groups in the system.
514      *
515      * @param flags additional option flags to modify the data returned
516      * @return a list of {@link PermissionGroupInfo} containing information about all of the known
517      *         permission groups
518      *
519      * @hide Pending API
520      */
521     @NonNull
getAllPermissionGroups( @ackageManager.PermissionGroupInfoFlags int flags)522     public List<PermissionGroupInfo> getAllPermissionGroups(
523             @PackageManager.PermissionGroupInfoFlags int flags) {
524         try {
525             final ParceledListSlice<PermissionGroupInfo> parceledList =
526                     mPermissionManager.getAllPermissionGroups(flags);
527             if (parceledList == null) {
528                 return Collections.emptyList();
529             }
530             return parceledList.getList();
531         } catch (RemoteException e) {
532             throw e.rethrowFromSystemServer();
533         }
534     }
535 
536     /**
537      * Checks whether a particular permissions has been revoked for a package by policy. Typically
538      * the device owner or the profile owner may apply such a policy. The user cannot grant policy
539      * revoked permissions, hence the only way for an app to get such a permission is by a policy
540      * change.
541      *
542      * @param packageName the name of the package you are checking against
543      * @param permissionName the name of the permission you are checking for
544      *
545      * @return whether the permission is restricted by policy
546      *
547      * @hide Pending API
548      */
549     @CheckResult
isPermissionRevokedByPolicy(@onNull String packageName, @NonNull String permissionName)550     public boolean isPermissionRevokedByPolicy(@NonNull String packageName,
551             @NonNull String permissionName) {
552         try {
553             return mPermissionManager.isPermissionRevokedByPolicy(packageName, permissionName,
554                     mContext.getUserId());
555         } catch (RemoteException e) {
556             throw e.rethrowFromSystemServer();
557         }
558     }
559 
560     /** @hide */
shouldTraceGrant( @onNull String packageName, @NonNull String permissionName, int userId)561     public static boolean shouldTraceGrant(
562             @NonNull String packageName, @NonNull String permissionName, int userId) {
563         // To be modified when debugging
564         // template: if ("".equals(packageName) && "".equals(permissionName)) return true;
565         return false;
566     }
567 
568     /**
569      * Grant a runtime permission to an application which the application does not already have. The
570      * permission must have been requested by the application. If the application is not allowed to
571      * hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or
572      * permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown.
573      * <p>
574      * <strong>Note: </strong>Using this API requires holding
575      * {@code android.permission.GRANT_RUNTIME_PERMISSIONS} and if the user ID is not the current
576      * user {@code android.permission.INTERACT_ACROSS_USERS_FULL}.
577      *
578      * @param packageName the package to which to grant the permission
579      * @param permissionName the permission name to grant
580      * @param user the user for which to grant the permission
581      *
582      * @see #revokeRuntimePermission(String, String, android.os.UserHandle, String)
583      *
584      * @hide
585      */
586     @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
587     //@SystemApi
grantRuntimePermission(@onNull String packageName, @NonNull String permissionName, @NonNull UserHandle user)588     public void grantRuntimePermission(@NonNull String packageName,
589             @NonNull String permissionName, @NonNull UserHandle user) {
590         if (DEBUG_TRACE_GRANTS
591                 && shouldTraceGrant(packageName, permissionName, user.getIdentifier())) {
592             Log.i(LOG_TAG_TRACE_GRANTS, "App " + mContext.getPackageName() + " is granting "
593                     + packageName + " "
594                     + permissionName + " for user " + user.getIdentifier(), new RuntimeException());
595         }
596         try {
597             mPermissionManager.grantRuntimePermission(packageName, permissionName,
598                     user.getIdentifier());
599         } catch (RemoteException e) {
600             throw e.rethrowFromSystemServer();
601         }
602     }
603 
604     /**
605      * Revoke a runtime permission that was previously granted by
606      * {@link #grantRuntimePermission(String, String, android.os.UserHandle)}. The permission must
607      * have been requested by and granted to the application. If the application is not allowed to
608      * hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or
609      * permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown.
610      * <p>
611      * <strong>Note: </strong>Using this API requires holding
612      * {@code android.permission.REVOKE_RUNTIME_PERMISSIONS} and if the user ID is not the current
613      * user {@code android.permission.INTERACT_ACROSS_USERS_FULL}.
614      *
615      * @param packageName the package from which to revoke the permission
616      * @param permName the permission name to revoke
617      * @param user the user for which to revoke the permission
618      * @param reason the reason for the revoke, or {@code null} for unspecified
619      *
620      * @see #grantRuntimePermission(String, String, android.os.UserHandle)
621      *
622      * @hide
623      */
624     @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
625     //@SystemApi
revokeRuntimePermission(@onNull String packageName, @NonNull String permName, @NonNull UserHandle user, @Nullable String reason)626     public void revokeRuntimePermission(@NonNull String packageName,
627             @NonNull String permName, @NonNull UserHandle user, @Nullable String reason) {
628         if (DEBUG_TRACE_PERMISSION_UPDATES
629                 && shouldTraceGrant(packageName, permName, user.getIdentifier())) {
630             Log.i(LOG_TAG, "App " + mContext.getPackageName() + " is revoking " + packageName + " "
631                     + permName + " for user " + user.getIdentifier() + " with reason "
632                     + reason, new RuntimeException());
633         }
634         try {
635             mPermissionManager
636                     .revokeRuntimePermission(packageName, permName, user.getIdentifier(), reason);
637         } catch (RemoteException e) {
638             throw e.rethrowFromSystemServer();
639         }
640     }
641 
642     /**
643      * Gets the state flags associated with a permission.
644      *
645      * @param packageName the package name for which to get the flags
646      * @param permissionName the permission for which to get the flags
647      * @param user the user for which to get permission flags
648      * @return the permission flags
649      *
650      * @hide
651      */
652     @PackageManager.PermissionFlags
653     @RequiresPermission(anyOf = {
654             android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
655             android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
656             android.Manifest.permission.GET_RUNTIME_PERMISSIONS
657     })
658     //@SystemApi
getPermissionFlags(@onNull String packageName, @NonNull String permissionName, @NonNull UserHandle user)659     public int getPermissionFlags(@NonNull String packageName, @NonNull String permissionName,
660             @NonNull UserHandle user) {
661         try {
662             return mPermissionManager.getPermissionFlags(packageName, permissionName,
663                     user.getIdentifier());
664         } catch (RemoteException e) {
665             throw e.rethrowFromSystemServer();
666         }
667     }
668 
669     /**
670      * Updates the flags associated with a permission by replacing the flags in the specified mask
671      * with the provided flag values.
672      *
673      * @param packageName The package name for which to update the flags
674      * @param permissionName The permission for which to update the flags
675      * @param flagMask The flags which to replace
676      * @param flagValues The flags with which to replace
677      * @param user The user for which to update the permission flags
678      *
679      * @hide
680      */
681     @RequiresPermission(anyOf = {
682             android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
683             android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
684     })
685     //@SystemApi
updatePermissionFlags(@onNull String packageName, @NonNull String permissionName, @PackageManager.PermissionFlags int flagMask, @PackageManager.PermissionFlags int flagValues, @NonNull UserHandle user)686     public void updatePermissionFlags(@NonNull String packageName, @NonNull String permissionName,
687             @PackageManager.PermissionFlags int flagMask,
688             @PackageManager.PermissionFlags int flagValues, @NonNull UserHandle user) {
689         if (DEBUG_TRACE_PERMISSION_UPDATES && shouldTraceGrant(packageName, permissionName,
690                 user.getIdentifier())) {
691             Log.i(LOG_TAG, "App " + mContext.getPackageName() + " is updating flags for "
692                     + packageName + " " + permissionName + " for user "
693                     + user.getIdentifier() + ": " + DebugUtils.flagsToString(
694                     PackageManager.class, "FLAG_PERMISSION_", flagMask) + " := "
695                     + DebugUtils.flagsToString(PackageManager.class, "FLAG_PERMISSION_",
696                     flagValues), new RuntimeException());
697         }
698         try {
699             final boolean checkAdjustPolicyFlagPermission =
700                     mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q;
701             mPermissionManager.updatePermissionFlags(packageName, permissionName, flagMask,
702                     flagValues, checkAdjustPolicyFlagPermission, user.getIdentifier());
703         } catch (RemoteException e) {
704             throw e.rethrowFromSystemServer();
705         }
706     }
707 
708     /**
709      * Gets the restricted permissions that have been allowlisted and the app is allowed to have
710      * them granted in their full form.
711      * <p>
712      * Permissions can be hard restricted which means that the app cannot hold them or soft
713      * restricted where the app can hold the permission but in a weaker form. Whether a permission
714      * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or
715      * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission
716      * declaration. Allowlisting a hard restricted permission allows for the to hold that permission
717      * and allowlisting a soft restricted permission allows the app to hold the permission in its
718      * full, unrestricted form.
719      * <p>
720      * There are four allowlists:
721      * <ol>
722      * <li>
723      * One for cases where the system permission policy allowlists a permission. This list
724      * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be
725      * accessed by pre-installed holders of a dedicated permission.
726      * <li>
727      * One for cases where the system allowlists the permission when upgrading from an OS version in
728      * which the permission was not restricted to an OS version in which the permission is
729      * restricted. This list corresponds to the
730      * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by
731      * pre-installed holders of a dedicated permission or the installer on record.
732      * <li>
733      * One for cases where the installer of the package allowlists a permission. This list
734      * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be
735      * accessed by pre-installed holders of a dedicated permission or the installer on record.
736      * </ol>
737      *
738      * @param packageName the app for which to get allowlisted permissions
739      * @param allowlistFlag the flag to determine which allowlist to query. Only one flag can be
740      *                      passed.
741      * @return the allowlisted permissions that are on any of the allowlists you query for
742      * @throws SecurityException if you try to access a allowlist that you have no access to
743      *
744      * @see #addAllowlistedRestrictedPermission(String, String, int)
745      * @see #removeAllowlistedRestrictedPermission(String, String, int)
746      * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM
747      * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE
748      * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER
749      *
750      * @hide Pending API
751      */
752     @NonNull
753     @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
754             conditional = true)
getAllowlistedRestrictedPermissions(@onNull String packageName, @PackageManager.PermissionWhitelistFlags int allowlistFlag)755     public Set<String> getAllowlistedRestrictedPermissions(@NonNull String packageName,
756             @PackageManager.PermissionWhitelistFlags int allowlistFlag) {
757         try {
758             final List<String> allowlist = mPermissionManager.getAllowlistedRestrictedPermissions(
759                     packageName, allowlistFlag, mContext.getUserId());
760             if (allowlist == null) {
761                 return Collections.emptySet();
762             }
763             return new ArraySet<>(allowlist);
764         } catch (RemoteException e) {
765             throw e.rethrowFromSystemServer();
766         }
767     }
768 
769     /**
770      * Adds a allowlisted restricted permission for an app.
771      * <p>
772      * Permissions can be hard restricted which means that the app cannot hold them or soft
773      * restricted where the app can hold the permission but in a weaker form. Whether a permission
774      * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or
775      * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission
776      * declaration. Allowlisting a hard restricted permission allows for the to hold that permission
777      * and allowlisting a soft restricted permission allows the app to hold the permission in its
778      * full, unrestricted form.
779      * <p>There are four allowlists:
780      * <ol>
781      * <li>
782      * One for cases where the system permission policy allowlists a permission. This list
783      * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be
784      * accessed by pre-installed holders of a dedicated permission.
785      * <li>
786      * One for cases where the system allowlists the permission when upgrading from an OS version in
787      * which the permission was not restricted to an OS version in which the permission is
788      * restricted. This list corresponds to the
789      * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by
790      * pre-installed holders of a dedicated permission or the installer on record.
791      * <li>
792      * One for cases where the installer of the package allowlists a permission. This list
793      * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be
794      * accessed by pre-installed holders of a dedicated permission or the installer on record.
795      * </ol>
796      * <p>
797      * You need to specify the allowlists for which to set the allowlisted permissions which will
798      * clear the previous allowlisted permissions and replace them with the provided ones.
799      *
800      * @param packageName the app for which to get allowlisted permissions
801      * @param permissionName the allowlisted permission to add
802      * @param allowlistFlags the allowlists to which to add. Passing multiple flags updates all
803      *                       specified allowlists.
804      * @return whether the permission was added to the allowlist
805      * @throws SecurityException if you try to modify a allowlist that you have no access to.
806      *
807      * @see #getAllowlistedRestrictedPermissions(String, int)
808      * @see #removeAllowlistedRestrictedPermission(String, String, int)
809      * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM
810      * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE
811      * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER
812      *
813      * @hide Pending API
814      */
815     @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
816             conditional = true)
addAllowlistedRestrictedPermission(@onNull String packageName, @NonNull String permissionName, @PackageManager.PermissionWhitelistFlags int allowlistFlags)817     public boolean addAllowlistedRestrictedPermission(@NonNull String packageName,
818             @NonNull String permissionName,
819             @PackageManager.PermissionWhitelistFlags int allowlistFlags) {
820         try {
821             return mPermissionManager.addAllowlistedRestrictedPermission(packageName,
822                     permissionName, allowlistFlags, mContext.getUserId());
823         } catch (RemoteException e) {
824             throw e.rethrowFromSystemServer();
825         }
826     }
827 
828     /**
829      * Removes a allowlisted restricted permission for an app.
830      * <p>
831      * Permissions can be hard restricted which means that the app cannot hold them or soft
832      * restricted where the app can hold the permission but in a weaker form. Whether a permission
833      * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or
834      * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission
835      * declaration. Allowlisting a hard restricted permission allows for the to hold that permission
836      * and allowlisting a soft restricted permission allows the app to hold the permission in its
837      * full, unrestricted form.
838      * <p>There are four allowlists:
839      * <ol>
840      * <li>
841      * One for cases where the system permission policy allowlists a permission. This list
842      * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be
843      * accessed by pre-installed holders of a dedicated permission.
844      * <li>
845      * One for cases where the system allowlists the permission when upgrading from an OS version in
846      * which the permission was not restricted to an OS version in which the permission is
847      * restricted. This list corresponds to the
848      * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by
849      * pre-installed holders of a dedicated permission or the installer on record.
850      * <li>
851      * One for cases where the installer of the package allowlists a permission. This list
852      * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be
853      * accessed by pre-installed holders of a dedicated permission or the installer on record.
854      * </ol>
855      * <p>
856      * You need to specify the allowlists for which to set the allowlisted permissions which will
857      * clear the previous allowlisted permissions and replace them with the provided ones.
858      *
859      * @param packageName the app for which to get allowlisted permissions
860      * @param permissionName the allowlisted permission to remove
861      * @param allowlistFlags the allowlists from which to remove. Passing multiple flags updates all
862      *                       specified allowlists.
863      * @return whether the permission was removed from the allowlist
864      * @throws SecurityException if you try to modify a allowlist that you have no access to.
865      *
866      * @see #getAllowlistedRestrictedPermissions(String, int)
867      * @see #addAllowlistedRestrictedPermission(String, String, int)
868      * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM
869      * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE
870      * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER
871      *
872      * @hide Pending API
873      */
874     @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
875             conditional = true)
removeAllowlistedRestrictedPermission(@onNull String packageName, @NonNull String permissionName, @PackageManager.PermissionWhitelistFlags int allowlistFlags)876     public boolean removeAllowlistedRestrictedPermission(@NonNull String packageName,
877             @NonNull String permissionName,
878             @PackageManager.PermissionWhitelistFlags int allowlistFlags) {
879         try {
880             return mPermissionManager.removeAllowlistedRestrictedPermission(packageName,
881                     permissionName, allowlistFlags, mContext.getUserId());
882         } catch (RemoteException e) {
883             throw e.rethrowFromSystemServer();
884         }
885     }
886 
887     /**
888      * Checks whether an application is exempted from having its permissions be automatically
889      * revoked when the app is unused for an extended period of time.
890      * <p>
891      * Only the installer on record that installed the given package, or a holder of
892      * {@code WHITELIST_AUTO_REVOKE_PERMISSIONS} is allowed to call this.
893      *
894      * @param packageName the app for which to set exemption
895      * @return whether the app is exempted
896      * @throws SecurityException if you you have no access to this
897      *
898      * @see #setAutoRevokeExempted
899      *
900      * @hide Pending API
901      */
902     @RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS,
903             conditional = true)
isAutoRevokeExempted(@onNull String packageName)904     public boolean isAutoRevokeExempted(@NonNull String packageName) {
905         try {
906             return mPermissionManager.isAutoRevokeExempted(packageName, mContext.getUserId());
907         } catch (RemoteException e) {
908             throw e.rethrowFromSystemServer();
909         }
910     }
911 
912     /**
913      * Marks an application exempted from having its permissions be automatically revoked when the
914      * app is unused for an extended period of time.
915      * <p>
916      * Only the installer on record that installed the given package is allowed to call this.
917      * <p>
918      * Packages start in exempted state, and it is the installer's responsibility to un-exempt the
919      * packages it installs, unless auto-revoking permissions from that package would cause
920      * breakages beyond having to re-request the permission(s).
921      *
922      * @param packageName the app for which to set exemption
923      * @param exempted whether the app should be exempted
924      * @return whether any change took effect
925      * @throws SecurityException if you you have no access to modify this
926      *
927      * @see #isAutoRevokeExempted
928      *
929      * @hide Pending API
930      */
931     @RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS,
932             conditional = true)
setAutoRevokeExempted(@onNull String packageName, boolean exempted)933     public boolean setAutoRevokeExempted(@NonNull String packageName, boolean exempted) {
934         try {
935             return mPermissionManager.setAutoRevokeExempted(packageName, exempted,
936                     mContext.getUserId());
937         } catch (RemoteException e) {
938             throw e.rethrowFromSystemServer();
939         }
940     }
941 
942     /**
943      * Get whether you should show UI with rationale for requesting a permission. You should do this
944      * only if you do not have the permission and the context in which the permission is requested
945      * does not clearly communicate to the user what would be the benefit from grating this
946      * permission.
947      *
948      * @param permissionName a permission your app wants to request
949      * @return whether you can show permission rationale UI
950      *
951      * @hide
952      */
953     //@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
shouldShowRequestPermissionRationale(@onNull String permissionName)954     public boolean shouldShowRequestPermissionRationale(@NonNull String permissionName) {
955         try {
956             final String packageName = mContext.getPackageName();
957             return mPermissionManager.shouldShowRequestPermissionRationale(packageName,
958                     permissionName, mContext.getUserId());
959         } catch (RemoteException e) {
960             throw e.rethrowFromSystemServer();
961         }
962     }
963 
964     /**
965      * Add a listener for permission changes for installed packages.
966      *
967      * @param listener the listener to add
968      *
969      * @hide
970      */
971     //@SystemApi
972     @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
addOnPermissionsChangeListener( @onNull PackageManager.OnPermissionsChangedListener listener)973     public void addOnPermissionsChangeListener(
974             @NonNull PackageManager.OnPermissionsChangedListener listener) {
975         synchronized (mPermissionListeners) {
976             if (mPermissionListeners.get(listener) != null) {
977                 return;
978             }
979             final OnPermissionsChangeListenerDelegate delegate =
980                     new OnPermissionsChangeListenerDelegate(listener, Looper.getMainLooper());
981             try {
982                 mPermissionManager.addOnPermissionsChangeListener(delegate);
983                 mPermissionListeners.put(listener, delegate);
984             } catch (RemoteException e) {
985                 throw e.rethrowFromSystemServer();
986             }
987         }
988     }
989 
990     /**
991      * Remove a listener for permission changes for installed packages.
992      *
993      * @param listener the listener to remove
994      *
995      * @hide
996      */
997     //@SystemApi
998     @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
removeOnPermissionsChangeListener( @onNull PackageManager.OnPermissionsChangedListener listener)999     public void removeOnPermissionsChangeListener(
1000             @NonNull PackageManager.OnPermissionsChangedListener listener) {
1001         synchronized (mPermissionListeners) {
1002             final IOnPermissionsChangeListener delegate = mPermissionListeners.get(listener);
1003             if (delegate != null) {
1004                 try {
1005                     mPermissionManager.removeOnPermissionsChangeListener(delegate);
1006                     mPermissionListeners.remove(listener);
1007                 } catch (RemoteException e) {
1008                     throw e.rethrowFromSystemServer();
1009                 }
1010             }
1011         }
1012     }
1013 
1014     /**
1015      * Gets the version of the runtime permission database.
1016      *
1017      * @return The database version, -1 when this is an upgrade from pre-Q, 0 when this is a fresh
1018      * install.
1019      *
1020      * @hide
1021      */
1022     @SystemApi
1023     @RequiresPermission(anyOf = {
1024             Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
1025             Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS
1026     })
getRuntimePermissionsVersion()1027     public @IntRange(from = 0) int getRuntimePermissionsVersion() {
1028         try {
1029             return mPackageManager.getRuntimePermissionsVersion(mContext.getUserId());
1030         } catch (RemoteException e) {
1031             throw e.rethrowFromSystemServer();
1032         }
1033     }
1034 
1035     /**
1036      * Sets the version of the runtime permission database.
1037      *
1038      * @param version The new version.
1039      *
1040      * @hide
1041      */
1042     @SystemApi
1043     @RequiresPermission(anyOf = {
1044             Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
1045             Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS
1046     })
setRuntimePermissionsVersion(@ntRangefrom = 0) int version)1047     public void setRuntimePermissionsVersion(@IntRange(from = 0) int version) {
1048         try {
1049             mPackageManager.setRuntimePermissionsVersion(version, mContext.getUserId());
1050         } catch (RemoteException e) {
1051             throw e.rethrowFromSystemServer();
1052         }
1053     }
1054 
1055     /**
1056      * Get set of permissions that have been split into more granular or dependent permissions.
1057      *
1058      * <p>E.g. before {@link android.os.Build.VERSION_CODES#Q} an app that was granted
1059      * {@link Manifest.permission#ACCESS_COARSE_LOCATION} could access the location while it was in
1060      * foreground and background. On platforms after {@link android.os.Build.VERSION_CODES#Q}
1061      * the location permission only grants location access while the app is in foreground. This
1062      * would break apps that target before {@link android.os.Build.VERSION_CODES#Q}. Hence whenever
1063      * such an old app asks for a location permission (i.e. the
1064      * {@link SplitPermissionInfo#getSplitPermission()}), then the
1065      * {@link Manifest.permission#ACCESS_BACKGROUND_LOCATION} permission (inside
1066      * {@link SplitPermissionInfo#getNewPermissions}) is added.
1067      *
1068      * <p>Note: Regular apps do not have to worry about this. The platform and permission controller
1069      * automatically add the new permissions where needed.
1070      *
1071      * @return All permissions that are split.
1072      */
getSplitPermissions()1073     public @NonNull List<SplitPermissionInfo> getSplitPermissions() {
1074         if (mSplitPermissionInfos != null) {
1075             return mSplitPermissionInfos;
1076         }
1077 
1078         List<SplitPermissionInfoParcelable> parcelableList;
1079         try {
1080             parcelableList = ActivityThread.getPermissionManager().getSplitPermissions();
1081         } catch (RemoteException e) {
1082             Slog.e(LOG_TAG, "Error getting split permissions", e);
1083             return Collections.emptyList();
1084         }
1085 
1086         mSplitPermissionInfos = splitPermissionInfoListToNonParcelableList(parcelableList);
1087 
1088         return mSplitPermissionInfos;
1089     }
1090 
1091     /**
1092      * Initialize the PermissionUsageHelper, which will register active app op listeners
1093      *
1094      * @hide
1095      */
initializeUsageHelper()1096     public void initializeUsageHelper() {
1097         if (mUsageHelper == null) {
1098             mUsageHelper = new PermissionUsageHelper(mContext);
1099         }
1100     }
1101 
1102     /**
1103      * Teardown the PermissionUsageHelper, removing listeners
1104      *
1105      * @hide
1106      */
tearDownUsageHelper()1107     public void tearDownUsageHelper() {
1108         if (mUsageHelper != null) {
1109             mUsageHelper.tearDown();
1110             mUsageHelper = null;
1111         }
1112     }
1113 
1114     /**
1115      * @return A list of permission groups currently or recently used by all apps by all users in
1116      * the current profile group.
1117      *
1118      * @hide
1119      */
1120     @TestApi
1121     @NonNull
1122     @RequiresPermission(Manifest.permission.GET_APP_OPS_STATS)
getIndicatorAppOpUsageData()1123     public List<PermissionGroupUsage> getIndicatorAppOpUsageData() {
1124         return getIndicatorAppOpUsageData(new AudioManager().isMicrophoneMute());
1125     }
1126 
1127     /**
1128      * @param micMuted whether to consider the microphone muted when retrieving audio ops
1129      * @return A list of permission groups currently or recently used by all apps by all users in
1130      * the current profile group.
1131      *
1132      * @hide
1133      */
1134     @TestApi
1135     @NonNull
1136     @RequiresPermission(Manifest.permission.GET_APP_OPS_STATS)
getIndicatorAppOpUsageData(boolean micMuted)1137     public List<PermissionGroupUsage> getIndicatorAppOpUsageData(boolean micMuted) {
1138         // Lazily initialize the usage helper
1139         initializeUsageHelper();
1140         return mUsageHelper.getOpUsageData(micMuted);
1141     }
1142 
1143     /**
1144      * Determine if a package should be shown in indicators. Only a select few roles, and the
1145      * system app itself, are hidden. These values are updated at most every 15 seconds.
1146      * @hide
1147      */
shouldShowPackageForIndicatorCached(@onNull Context context, @NonNull String packageName)1148     public static boolean shouldShowPackageForIndicatorCached(@NonNull Context context,
1149             @NonNull String packageName) {
1150         return !getIndicatorExemptedPackages(context).contains(packageName);
1151     }
1152 
1153     /**
1154      * Get the list of packages that are not shown by the indicators. Only a select few roles, and
1155      * the system app itself, are hidden. These values are updated at most every 15 seconds.
1156      * @hide
1157      */
getIndicatorExemptedPackages(@onNull Context context)1158     public static Set<String> getIndicatorExemptedPackages(@NonNull Context context) {
1159         updateIndicatorExemptedPackages(context);
1160         ArraySet<String> pkgNames = new ArraySet<>();
1161         pkgNames.add(SYSTEM_PKG);
1162         for (int i = 0; i < INDICATOR_EXEMPTED_PACKAGES.length; i++) {
1163             String exemptedPackage = INDICATOR_EXEMPTED_PACKAGES[i];
1164             if (exemptedPackage != null) {
1165                 pkgNames.add(exemptedPackage);
1166             }
1167         }
1168         return pkgNames;
1169     }
1170 
1171     /**
1172      * Update the cached indicator exempted packages
1173      * @hide
1174      */
updateIndicatorExemptedPackages(@onNull Context context)1175     public static void updateIndicatorExemptedPackages(@NonNull Context context) {
1176         long now = SystemClock.elapsedRealtime();
1177         if (sLastIndicatorUpdateTime == -1
1178                 || (now - sLastIndicatorUpdateTime) > EXEMPTED_INDICATOR_ROLE_UPDATE_FREQUENCY_MS) {
1179             sLastIndicatorUpdateTime = now;
1180             for (int i = 0; i < EXEMPTED_ROLES.length; i++) {
1181                 INDICATOR_EXEMPTED_PACKAGES[i] = context.getString(EXEMPTED_ROLES[i]);
1182             }
1183         }
1184     }
1185     /**
1186      * Gets the list of packages that have permissions that specified
1187      * {@code requestDontAutoRevokePermissions=true} in their
1188      * {@code application} manifest declaration.
1189      *
1190      * @return the list of packages for current user
1191      * @hide
1192      */
1193     @SystemApi
1194     @NonNull
1195     @RequiresPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY)
getAutoRevokeExemptionRequestedPackages()1196     public Set<String> getAutoRevokeExemptionRequestedPackages() {
1197         try {
1198             return CollectionUtils.toSet(mPermissionManager.getAutoRevokeExemptionRequestedPackages(
1199                     mContext.getUser().getIdentifier()));
1200         } catch (RemoteException e) {
1201             throw e.rethrowFromSystemServer();
1202         }
1203     }
1204 
1205     /**
1206      * Gets the list of packages that have permissions that specified
1207      * {@code autoRevokePermissions=disallowed} in their
1208      * {@code application} manifest declaration.
1209      *
1210      * @return the list of packages for current user
1211      * @hide
1212      */
1213     @SystemApi
1214     @NonNull
1215     @RequiresPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY)
getAutoRevokeExemptionGrantedPackages()1216     public Set<String> getAutoRevokeExemptionGrantedPackages() {
1217         try {
1218             return CollectionUtils.toSet(mPermissionManager.getAutoRevokeExemptionGrantedPackages(
1219                     mContext.getUser().getIdentifier()));
1220         } catch (RemoteException e) {
1221             throw e.rethrowFromSystemServer();
1222         }
1223     }
1224 
splitPermissionInfoListToNonParcelableList( List<SplitPermissionInfoParcelable> parcelableList)1225     private List<SplitPermissionInfo> splitPermissionInfoListToNonParcelableList(
1226             List<SplitPermissionInfoParcelable> parcelableList) {
1227         final int size = parcelableList.size();
1228         List<SplitPermissionInfo> list = new ArrayList<>(size);
1229         for (int i = 0; i < size; i++) {
1230             list.add(new SplitPermissionInfo(parcelableList.get(i)));
1231         }
1232         return list;
1233     }
1234 
1235     /**
1236      * Converts a {@link List} of {@link SplitPermissionInfo} into a List of
1237      * {@link SplitPermissionInfoParcelable} and returns it.
1238      * @hide
1239      */
splitPermissionInfoListToParcelableList( List<SplitPermissionInfo> splitPermissionsList)1240     public static List<SplitPermissionInfoParcelable> splitPermissionInfoListToParcelableList(
1241             List<SplitPermissionInfo> splitPermissionsList) {
1242         final int size = splitPermissionsList.size();
1243         List<SplitPermissionInfoParcelable> outList = new ArrayList<>(size);
1244         for (int i = 0; i < size; i++) {
1245             SplitPermissionInfo info = splitPermissionsList.get(i);
1246             outList.add(new SplitPermissionInfoParcelable(
1247                     info.getSplitPermission(), info.getNewPermissions(), info.getTargetSdk()));
1248         }
1249         return outList;
1250     }
1251 
1252     /**
1253      * A permission that was added in a previous API level might have split into several
1254      * permissions. This object describes one such split.
1255      */
1256     @Immutable
1257     public static final class SplitPermissionInfo {
1258         private @NonNull final SplitPermissionInfoParcelable mSplitPermissionInfoParcelable;
1259 
1260         @Override
equals(@ullable Object o)1261         public boolean equals(@Nullable Object o) {
1262             if (this == o) return true;
1263             if (o == null || getClass() != o.getClass()) return false;
1264             SplitPermissionInfo that = (SplitPermissionInfo) o;
1265             return mSplitPermissionInfoParcelable.equals(that.mSplitPermissionInfoParcelable);
1266         }
1267 
1268         @Override
hashCode()1269         public int hashCode() {
1270             return mSplitPermissionInfoParcelable.hashCode();
1271         }
1272 
1273         /**
1274          * Get the permission that is split.
1275          */
getSplitPermission()1276         public @NonNull String getSplitPermission() {
1277             return mSplitPermissionInfoParcelable.getSplitPermission();
1278         }
1279 
1280         /**
1281          * Get the permissions that are added.
1282          */
getNewPermissions()1283         public @NonNull List<String> getNewPermissions() {
1284             return mSplitPermissionInfoParcelable.getNewPermissions();
1285         }
1286 
1287         /**
1288          * Get the target API level when the permission was split.
1289          */
getTargetSdk()1290         public int getTargetSdk() {
1291             return mSplitPermissionInfoParcelable.getTargetSdk();
1292         }
1293 
1294         /**
1295          * Constructs a split permission.
1296          *
1297          * @param splitPerm old permission that will be split
1298          * @param newPerms list of new permissions that {@code rootPerm} will be split into
1299          * @param targetSdk apps targetting SDK versions below this will have {@code rootPerm}
1300          * split into {@code newPerms}
1301          * @hide
1302          */
SplitPermissionInfo(@onNull String splitPerm, @NonNull List<String> newPerms, int targetSdk)1303         public SplitPermissionInfo(@NonNull String splitPerm, @NonNull List<String> newPerms,
1304                 int targetSdk) {
1305             this(new SplitPermissionInfoParcelable(splitPerm, newPerms, targetSdk));
1306         }
1307 
SplitPermissionInfo(@onNull SplitPermissionInfoParcelable parcelable)1308         private SplitPermissionInfo(@NonNull SplitPermissionInfoParcelable parcelable) {
1309             mSplitPermissionInfoParcelable = parcelable;
1310         }
1311     }
1312 
1313     /**
1314      * Starts a one-time permission session for a given package.
1315      * @see #startOneTimePermissionSession(String, long, long, int, int)
1316      * @hide
1317      * @deprecated Use {@link #startOneTimePermissionSession(String, long, long, int, int)} instead
1318      */
1319     @Deprecated
1320     @SystemApi
1321     @RequiresPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS)
startOneTimePermissionSession(@onNull String packageName, long timeoutMillis, @ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer, @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive)1322     public void startOneTimePermissionSession(@NonNull String packageName, long timeoutMillis,
1323             @ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer,
1324             @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive) {
1325         startOneTimePermissionSession(packageName, timeoutMillis, -1,
1326                 importanceToResetTimer, importanceToKeepSessionAlive);
1327     }
1328 
1329     /**
1330      * Starts a one-time permission session for a given package. A one-time permission session is
1331      * ended if app becomes inactive. Inactivity is defined as the package's uid importance level
1332      * staying > importanceToResetTimer for timeoutMillis milliseconds. If the package's uid
1333      * importance level goes <= importanceToResetTimer then the timer is reset and doesn't start
1334      * until going > importanceToResetTimer.
1335      * <p>
1336      * When this timeoutMillis is reached if the importance level is <= importanceToKeepSessionAlive
1337      * then the session is extended until either the importance goes above
1338      * importanceToKeepSessionAlive which will end the session or <= importanceToResetTimer which
1339      * will continue the session and reset the timer.
1340      * </p>
1341      * <p>
1342      * Importance levels are defined in {@link android.app.ActivityManager.RunningAppProcessInfo}.
1343      * </p>
1344      * <p>
1345      * Once the session ends
1346      * {@link PermissionControllerService#onOneTimePermissionSessionTimeout(String)} is invoked.
1347      * </p>
1348      * <p>
1349      * Note that if there is currently an active session for a package a new one isn't created but
1350      * each parameter of the existing one will be updated to the more aggressive of both sessions.
1351      * This means that durations will be set to the shortest parameter and importances will be set
1352      * to the lowest one.
1353      * </p>
1354      * @param packageName The package to start a one-time permission session for
1355      * @param timeoutMillis Number of milliseconds for an app to be in an inactive state
1356      * @param revokeAfterKilledDelayMillis Number of milliseconds to wait before revoking on the
1357      *                                     event an app is terminated. Set to -1 to use default
1358      *                                     value for the device.
1359      * @param importanceToResetTimer The least important level to uid must be to reset the timer
1360      * @param importanceToKeepSessionAlive The least important level the uid must be to keep the
1361      *                                     session alive
1362      *
1363      * @hide
1364      */
1365     @SystemApi
1366     @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)1367     public void startOneTimePermissionSession(@NonNull String packageName,
1368             @DurationMillisLong long timeoutMillis,
1369             @DurationMillisLong long revokeAfterKilledDelayMillis,
1370             @ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer,
1371             @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive) {
1372         try {
1373             mPermissionManager.startOneTimePermissionSession(packageName, mContext.getUserId(),
1374                     timeoutMillis, revokeAfterKilledDelayMillis);
1375         } catch (RemoteException e) {
1376             e.rethrowFromSystemServer();
1377         }
1378     }
1379 
1380     /**
1381      * Stops the one-time permission session for the package. The callback to the end of session is
1382      * not invoked. If there is no one-time session for the package then nothing happens.
1383      *
1384      * @param packageName Package to stop the one-time permission session for
1385      *
1386      * @hide
1387      */
1388     @SystemApi
1389     @RequiresPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS)
stopOneTimePermissionSession(@onNull String packageName)1390     public void stopOneTimePermissionSession(@NonNull String packageName) {
1391         try {
1392             mPermissionManager.stopOneTimePermissionSession(packageName,
1393                     mContext.getUserId());
1394         } catch (RemoteException e) {
1395             e.rethrowFromSystemServer();
1396         }
1397     }
1398 
1399     /**
1400      * Checks whether the package with the given pid/uid can read device identifiers.
1401      *
1402      * @param packageName      the name of the package to be checked for identifier access
1403      * @param message          the message to be used for logging during identifier access
1404      *                         verification
1405      * @param callingFeatureId the feature in the package
1406      * @param pid              the process id of the package to be checked
1407      * @param uid              the uid of the package to be checked
1408      * @return {@link PackageManager#PERMISSION_GRANTED} if the package is allowed identifier
1409      * access, {@link PackageManager#PERMISSION_DENIED} otherwise
1410      * @hide
1411      */
1412     @SystemApi
checkDeviceIdentifierAccess(@ullable String packageName, @Nullable String message, @Nullable String callingFeatureId, int pid, int uid)1413     public int checkDeviceIdentifierAccess(@Nullable String packageName, @Nullable String message,
1414             @Nullable String callingFeatureId, int pid, int uid) {
1415         return mLegacyPermissionManager.checkDeviceIdentifierAccess(packageName, message,
1416                 callingFeatureId, pid, uid);
1417     }
1418 
1419     /**
1420      * Registers an attribution source with the OS. An app can only register an attribution
1421      * source for itself. Once an attribution source has been registered another app can
1422      * check whether this registration exists and thus trust the payload in the source
1423      * object. This is important for permission checking and specifically for app op blaming
1424      * since a malicious app should not be able to force the OS to blame another app
1425      * that doesn't participate in an attribution chain.
1426      *
1427      * @param source The attribution source to register.
1428      * @return The registered new attribution source.
1429      *
1430      * @see #isRegisteredAttributionSource(AttributionSource)
1431      *
1432      * @hide
1433      */
1434     @TestApi
registerAttributionSource(@onNull AttributionSource source)1435     public @NonNull AttributionSource registerAttributionSource(@NonNull AttributionSource source) {
1436         // We use a shared static token for sources that are not registered since the token's
1437         // only used for process death detection. If we are about to use the source for security
1438         // enforcement we need to replace the binder with a unique one.
1439         final AttributionSource registeredSource = source.withToken(new Binder());
1440         try {
1441             mPermissionManager.registerAttributionSource(registeredSource.asState());
1442         } catch (RemoteException e) {
1443             e.rethrowFromSystemServer();
1444         }
1445         return registeredSource;
1446     }
1447 
1448     /**
1449      * Checks whether an attribution source is registered.
1450      *
1451      * @param source The attribution source to check.
1452      * @return Whether this is a registered source.
1453      *
1454      * @see #registerAttributionSource(AttributionSource)
1455      *
1456      * @hide
1457      */
isRegisteredAttributionSource(@onNull AttributionSource source)1458     public boolean isRegisteredAttributionSource(@NonNull AttributionSource source) {
1459         try {
1460             return mPermissionManager.isRegisteredAttributionSource(source.asState());
1461         } catch (RemoteException e) {
1462             e.rethrowFromSystemServer();
1463         }
1464         return false;
1465     }
1466 
1467     /**
1468      * Revoke the POST_NOTIFICATIONS permission, without killing the app. This method must ONLY BE
1469      * USED in CTS or local tests.
1470      *
1471      * @param packageName The package to be revoked
1472      * @param userId The user for which to revoke
1473      *
1474      * @hide
1475      */
1476     @TestApi
1477     @RequiresPermission(Manifest.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL)
revokePostNotificationPermissionWithoutKillForTest(@onNull String packageName, int userId)1478     public void revokePostNotificationPermissionWithoutKillForTest(@NonNull String packageName,
1479             int userId) {
1480         try {
1481             mPermissionManager.revokePostNotificationPermissionWithoutKillForTest(packageName,
1482                     userId);
1483         } catch (RemoteException e) {
1484             e.rethrowFromSystemServer();
1485         }
1486     }
1487 
1488     // Only warn once for assuming that root or system UID has a permission
1489     // to reduce duplicate logcat output.
1490     private static volatile boolean sShouldWarnMissingActivityManager = true;
1491 
1492     /* @hide */
checkPermissionUncached(@ullable String permission, int pid, int uid)1493     private static int checkPermissionUncached(@Nullable String permission, int pid, int uid) {
1494         final IActivityManager am = ActivityManager.getService();
1495         if (am == null) {
1496             // Well this is super awkward; we somehow don't have an active ActivityManager
1497             // instance. If we're testing a root or system UID, then they totally have whatever
1498             // permission this is.
1499             final int appId = UserHandle.getAppId(uid);
1500             if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) {
1501                 if (sShouldWarnMissingActivityManager) {
1502                     Slog.w(LOG_TAG, "Missing ActivityManager; assuming " + uid + " holds "
1503                             + permission);
1504                     sShouldWarnMissingActivityManager = false;
1505                 }
1506                 return PackageManager.PERMISSION_GRANTED;
1507             }
1508             Slog.w(LOG_TAG, "Missing ActivityManager; assuming " + uid + " does not hold "
1509                     + permission);
1510             return PackageManager.PERMISSION_DENIED;
1511         }
1512         try {
1513             sShouldWarnMissingActivityManager = true;
1514             return am.checkPermission(permission, pid, uid);
1515         } catch (RemoteException e) {
1516             throw e.rethrowFromSystemServer();
1517         }
1518     }
1519 
1520     /**
1521      * Identifies a permission query.
1522      *
1523      * N.B. we include the checking pid for tracking purposes but don't include it in the equality
1524      * comparison: we use only uid for the actual security check, so comparing pid would result
1525      * in spurious misses.
1526      *
1527      * @hide
1528      */
1529     @Immutable
1530     private static final class PermissionQuery {
1531         final String permission;
1532         final int pid;
1533         final int uid;
1534 
PermissionQuery(@ullable String permission, int pid, int uid)1535         PermissionQuery(@Nullable String permission, int pid, int uid) {
1536             this.permission = permission;
1537             this.pid = pid;
1538             this.uid = uid;
1539         }
1540 
1541         @Override
toString()1542         public String toString() {
1543             return String.format("PermissionQuery(permission=\"%s\", pid=%s, uid=%s)",
1544                     permission, pid, uid);
1545         }
1546 
1547         @Override
hashCode()1548         public int hashCode() {
1549             // N.B. pid doesn't count toward equality and therefore shouldn't count for
1550             // hashing either.
1551             int hash = Objects.hashCode(permission);
1552             hash = hash * 13 + Objects.hashCode(uid);
1553             return hash;
1554         }
1555 
1556         @Override
equals(@ullable Object rval)1557         public boolean equals(@Nullable Object rval) {
1558             // N.B. pid doesn't count toward equality!
1559             if (rval == null) {
1560                 return false;
1561             }
1562             PermissionQuery other;
1563             try {
1564                 other = (PermissionQuery) rval;
1565             } catch (ClassCastException ex) {
1566                 return false;
1567             }
1568             return uid == other.uid
1569                     && Objects.equals(permission, other.permission);
1570         }
1571     }
1572 
1573     /** @hide */
1574     public static final String CACHE_KEY_PACKAGE_INFO = "cache_key.package_info";
1575 
1576     /** @hide */
1577     private static final PropertyInvalidatedCache<PermissionQuery, Integer> sPermissionCache =
1578             new PropertyInvalidatedCache<PermissionQuery, Integer>(
1579                     2048, CACHE_KEY_PACKAGE_INFO, "checkPermission") {
1580                 @Override
1581                 public Integer recompute(PermissionQuery query) {
1582                     return checkPermissionUncached(query.permission, query.pid, query.uid);
1583                 }
1584             };
1585 
1586     /** @hide */
checkPermission(@ullable String permission, int pid, int uid)1587     public static int checkPermission(@Nullable String permission, int pid, int uid) {
1588         return sPermissionCache.query(new PermissionQuery(permission, pid, uid));
1589     }
1590 
1591     /**
1592      * Make checkPermission() above bypass the permission cache in this process.
1593      *
1594      * @hide
1595      */
disablePermissionCache()1596     public static void disablePermissionCache() {
1597         sPermissionCache.disableLocal();
1598     }
1599 
1600     /**
1601      * Like PermissionQuery, but for permission checks based on a package name instead of
1602      * a UID.
1603      */
1604     @Immutable
1605     private static final class PackageNamePermissionQuery {
1606         final String permName;
1607         final String pkgName;
1608         @UserIdInt
1609         final int userId;
1610 
PackageNamePermissionQuery(@ullable String permName, @Nullable String pkgName, @UserIdInt int userId)1611         PackageNamePermissionQuery(@Nullable String permName, @Nullable String pkgName,
1612                 @UserIdInt int userId) {
1613             this.permName = permName;
1614             this.pkgName = pkgName;
1615             this.userId = userId;
1616         }
1617 
1618         @Override
toString()1619         public String toString() {
1620             return String.format(
1621                     "PackageNamePermissionQuery(pkgName=\"%s\", permName=\"%s, userId=%s\")",
1622                     pkgName, permName, userId);
1623         }
1624 
1625         @Override
hashCode()1626         public int hashCode() {
1627             return Objects.hash(permName, pkgName, userId);
1628         }
1629 
1630         @Override
equals(@ullable Object rval)1631         public boolean equals(@Nullable Object rval) {
1632             if (rval == null) {
1633                 return false;
1634             }
1635             PackageNamePermissionQuery other;
1636             try {
1637                 other = (PackageNamePermissionQuery) rval;
1638             } catch (ClassCastException ex) {
1639                 return false;
1640             }
1641             return Objects.equals(permName, other.permName)
1642                     && Objects.equals(pkgName, other.pkgName)
1643                     && userId == other.userId;
1644         }
1645     }
1646 
1647     /* @hide */
checkPackageNamePermissionUncached( String permName, String pkgName, @UserIdInt int userId)1648     private static int checkPackageNamePermissionUncached(
1649             String permName, String pkgName, @UserIdInt int userId) {
1650         try {
1651             return ActivityThread.getPackageManager().checkPermission(
1652                     permName, pkgName, userId);
1653         } catch (RemoteException e) {
1654             throw e.rethrowFromSystemServer();
1655         }
1656     }
1657 
1658     /* @hide */
1659     private static PropertyInvalidatedCache<PackageNamePermissionQuery, Integer>
1660             sPackageNamePermissionCache =
1661             new PropertyInvalidatedCache<PackageNamePermissionQuery, Integer>(
1662                     16, CACHE_KEY_PACKAGE_INFO, "checkPackageNamePermission") {
1663                 @Override
1664                 public Integer recompute(PackageNamePermissionQuery query) {
1665                     return checkPackageNamePermissionUncached(
1666                             query.permName, query.pkgName, query.userId);
1667                 }
1668                 @Override
1669                 public boolean bypass(PackageNamePermissionQuery query) {
1670                     return query.userId < 0;
1671                 }
1672             };
1673 
1674     /**
1675      * Check whether a package has a permission.
1676      *
1677      * @hide
1678      */
checkPackageNamePermission(String permName, String pkgName, @UserIdInt int userId)1679     public static int checkPackageNamePermission(String permName, String pkgName,
1680             @UserIdInt int userId) {
1681         return sPackageNamePermissionCache.query(
1682                 new PackageNamePermissionQuery(permName, pkgName, userId));
1683     }
1684 
1685     /**
1686      * Make checkPackageNamePermission() bypass the cache in this process.
1687      *
1688      * @hide
1689      */
disablePackageNamePermissionCache()1690     public static void disablePackageNamePermissionCache() {
1691         sPackageNamePermissionCache.disableLocal();
1692     }
1693 
1694     private final class OnPermissionsChangeListenerDelegate
1695             extends IOnPermissionsChangeListener.Stub implements Handler.Callback{
1696         private static final int MSG_PERMISSIONS_CHANGED = 1;
1697 
1698         private final PackageManager.OnPermissionsChangedListener mListener;
1699         private final Handler mHandler;
1700 
OnPermissionsChangeListenerDelegate( PackageManager.OnPermissionsChangedListener listener, Looper looper)1701         public OnPermissionsChangeListenerDelegate(
1702                 PackageManager.OnPermissionsChangedListener listener, Looper looper) {
1703             mListener = listener;
1704             mHandler = new Handler(looper, this);
1705         }
1706 
1707         @Override
onPermissionsChanged(int uid)1708         public void onPermissionsChanged(int uid) {
1709             mHandler.obtainMessage(MSG_PERMISSIONS_CHANGED, uid, 0).sendToTarget();
1710         }
1711 
1712         @Override
handleMessage(Message msg)1713         public boolean handleMessage(Message msg) {
1714             switch (msg.what) {
1715                 case MSG_PERMISSIONS_CHANGED: {
1716                     final int uid = msg.arg1;
1717                     mListener.onPermissionsChanged(uid);
1718                     return true;
1719                 }
1720                 default:
1721                     return false;
1722             }
1723         }
1724     }
1725 }
1726