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