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