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