• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 com.android.server.pm.permission;
18 
19 import static android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY;
20 import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
21 import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
22 import static android.Manifest.permission.RECORD_AUDIO;
23 import static android.Manifest.permission.UPDATE_APP_OPS_STATS;
24 import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
25 import static android.app.AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE;
26 import static android.app.AppOpsManager.ATTRIBUTION_FLAGS_NONE;
27 import static android.app.AppOpsManager.MODE_ALLOWED;
28 import static android.app.AppOpsManager.MODE_ERRORED;
29 import static android.app.AppOpsManager.MODE_IGNORED;
30 import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISALLOWED;
31 import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISCOURAGED;
32 import static android.content.pm.PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT;
33 import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
34 import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
35 import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE;
36 import static android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME;
37 import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
38 import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
39 import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
40 import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
41 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
42 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
43 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
44 import static android.content.pm.PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY;
45 import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
46 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
47 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
48 import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER;
49 import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM;
50 import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE;
51 import static android.content.pm.PackageManager.MASK_PERMISSION_FLAGS_ALL;
52 import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
53 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
54 import static android.permission.PermissionManager.KILL_APP_REASON_GIDS_CHANGED;
55 import static android.permission.PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED;
56 
57 import static com.android.server.pm.ApexManager.MATCH_ACTIVE_PACKAGE;
58 import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
59 import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
60 import static com.android.server.pm.PackageManagerService.DEBUG_PERMISSIONS;
61 import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
62 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
63 
64 import static java.util.concurrent.TimeUnit.SECONDS;
65 
66 import android.Manifest;
67 import android.annotation.AppIdInt;
68 import android.annotation.IntDef;
69 import android.annotation.NonNull;
70 import android.annotation.Nullable;
71 import android.annotation.UserIdInt;
72 import android.app.ActivityManager;
73 import android.app.AppOpsManager;
74 import android.app.AppOpsManager.AttributionFlags;
75 import android.app.IActivityManager;
76 import android.app.admin.DevicePolicyManagerInternal;
77 import android.compat.annotation.ChangeId;
78 import android.compat.annotation.EnabledAfter;
79 import android.content.AttributionSource;
80 import android.content.AttributionSourceState;
81 import android.content.Context;
82 import android.content.PermissionChecker;
83 import android.content.pm.ApplicationInfo;
84 import android.content.pm.FeatureInfo;
85 import android.content.pm.PackageManager;
86 import android.content.pm.PackageManager.PermissionGroupInfoFlags;
87 import android.content.pm.PackageManager.PermissionInfoFlags;
88 import android.content.pm.PackageManager.PermissionWhitelistFlags;
89 import android.content.pm.PackageManagerInternal;
90 import android.content.pm.PackageParser;
91 import android.content.pm.ParceledListSlice;
92 import android.content.pm.PermissionGroupInfo;
93 import android.content.pm.PermissionInfo;
94 import android.content.pm.parsing.component.ParsedPermission;
95 import android.content.pm.parsing.component.ParsedPermissionGroup;
96 import android.content.pm.permission.SplitPermissionInfoParcelable;
97 import android.metrics.LogMaker;
98 import android.os.AsyncTask;
99 import android.os.Binder;
100 import android.os.Build;
101 import android.os.Debug;
102 import android.os.Handler;
103 import android.os.HandlerThread;
104 import android.os.IBinder;
105 import android.os.Looper;
106 import android.os.Message;
107 import android.os.Process;
108 import android.os.RemoteCallbackList;
109 import android.os.RemoteException;
110 import android.os.ServiceManager;
111 import android.os.Trace;
112 import android.os.UserHandle;
113 import android.os.UserManager;
114 import android.os.storage.StorageManager;
115 import android.permission.IOnPermissionsChangeListener;
116 import android.permission.IPermissionChecker;
117 import android.permission.IPermissionManager;
118 import android.permission.PermissionCheckerManager;
119 import android.permission.PermissionControllerManager;
120 import android.permission.PermissionManager;
121 import android.permission.PermissionManagerInternal;
122 import android.text.TextUtils;
123 import android.util.ArrayMap;
124 import android.util.ArraySet;
125 import android.util.DebugUtils;
126 import android.util.EventLog;
127 import android.util.IntArray;
128 import android.util.Log;
129 import android.util.Slog;
130 import android.util.SparseArray;
131 import android.util.SparseBooleanArray;
132 
133 import com.android.internal.annotations.GuardedBy;
134 import com.android.internal.compat.IPlatformCompat;
135 import com.android.internal.logging.MetricsLogger;
136 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
137 import com.android.internal.os.RoSystemProperties;
138 import com.android.internal.util.ArrayUtils;
139 import com.android.internal.util.CollectionUtils;
140 import com.android.internal.util.DumpUtils;
141 import com.android.internal.util.IntPair;
142 import com.android.internal.util.Preconditions;
143 import com.android.internal.util.function.TriFunction;
144 import com.android.internal.util.function.pooled.PooledLambda;
145 import com.android.server.FgThread;
146 import com.android.server.LocalServices;
147 import com.android.server.ServiceThread;
148 import com.android.server.SystemConfig;
149 import com.android.server.Watchdog;
150 import com.android.server.pm.ApexManager;
151 import com.android.server.pm.PackageSetting;
152 import com.android.server.pm.UserManagerInternal;
153 import com.android.server.pm.UserManagerService;
154 import com.android.server.pm.parsing.PackageInfoUtils;
155 import com.android.server.pm.parsing.pkg.AndroidPackage;
156 import com.android.server.pm.permission.PermissionManagerServiceInternal.HotwordDetectionServiceProvider;
157 import com.android.server.pm.permission.PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener;
158 import com.android.server.policy.PermissionPolicyInternal;
159 import com.android.server.policy.SoftRestrictedPermissionPolicy;
160 
161 import libcore.util.EmptyArray;
162 
163 import java.io.FileDescriptor;
164 import java.io.PrintWriter;
165 import java.lang.annotation.Retention;
166 import java.lang.annotation.RetentionPolicy;
167 import java.util.ArrayList;
168 import java.util.Arrays;
169 import java.util.Collection;
170 import java.util.Collections;
171 import java.util.HashMap;
172 import java.util.Iterator;
173 import java.util.List;
174 import java.util.Map;
175 import java.util.NoSuchElementException;
176 import java.util.Objects;
177 import java.util.Set;
178 import java.util.WeakHashMap;
179 import java.util.concurrent.CompletableFuture;
180 import java.util.concurrent.ConcurrentHashMap;
181 import java.util.concurrent.ExecutionException;
182 import java.util.concurrent.TimeUnit;
183 import java.util.concurrent.TimeoutException;
184 import java.util.concurrent.atomic.AtomicBoolean;
185 import java.util.concurrent.atomic.AtomicInteger;
186 import java.util.function.BiFunction;
187 
188 /**
189  * Manages all permissions and handles permissions related tasks.
190  */
191 public class PermissionManagerService extends IPermissionManager.Stub {
192     private static final String TAG = "PackageManager";
193     private static final String LOG_TAG = PermissionManagerService.class.getSimpleName();
194 
195     private static final long BACKUP_TIMEOUT_MILLIS = SECONDS.toMillis(60);
196 
197     // For automotive products, CarService enforces allow-listing of the privileged permissions
198     // com.android.car is the package name which declares auto specific permissions
199     private static final String CAR_PACKAGE_NAME = "com.android.car";
200 
201     /** Cap the size of permission trees that 3rd party apps can define; in characters of text */
202     private static final int MAX_PERMISSION_TREE_FOOTPRINT = 32768;
203     /** Empty array to avoid allocations */
204     private static final int[] EMPTY_INT_ARRAY = new int[0];
205 
206     /**
207      * When these flags are set, the system should not automatically modify the permission grant
208      * state.
209      */
210     private static final int BLOCKING_PERMISSION_FLAGS = FLAG_PERMISSION_SYSTEM_FIXED
211             | FLAG_PERMISSION_POLICY_FIXED
212             | FLAG_PERMISSION_GRANTED_BY_DEFAULT;
213 
214     /** Permission flags set by the user */
215     private static final int USER_PERMISSION_FLAGS = FLAG_PERMISSION_USER_SET
216             | FLAG_PERMISSION_USER_FIXED;
217 
218     /** All storage permissions */
219     private static final List<String> STORAGE_PERMISSIONS = new ArrayList<>();
220     /** All nearby devices permissions */
221     private static final List<String> NEARBY_DEVICES_PERMISSIONS = new ArrayList<>();
222 
223     /** If the permission of the value is granted, so is the key */
224     private static final Map<String, String> FULLER_PERMISSION_MAP = new HashMap<>();
225 
226     /** Map of IBinder -> Running AttributionSource */
227     private static final ConcurrentHashMap<IBinder, RegisteredAttribution>
228             sRunningAttributionSources = new ConcurrentHashMap<>();
229 
230     static {
FULLER_PERMISSION_MAP.put(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION)231         FULLER_PERMISSION_MAP.put(Manifest.permission.ACCESS_COARSE_LOCATION,
232                 Manifest.permission.ACCESS_FINE_LOCATION);
FULLER_PERMISSION_MAP.put(Manifest.permission.INTERACT_ACROSS_USERS, Manifest.permission.INTERACT_ACROSS_USERS_FULL)233         FULLER_PERMISSION_MAP.put(Manifest.permission.INTERACT_ACROSS_USERS,
234                 Manifest.permission.INTERACT_ACROSS_USERS_FULL);
235         STORAGE_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE);
236         STORAGE_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
237         STORAGE_PERMISSIONS.add(Manifest.permission.ACCESS_MEDIA_LOCATION);
238         NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_ADVERTISE);
239         NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_CONNECT);
240         NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_SCAN);
241     }
242 
243     /** Set of source package names for Privileged Permission Allowlist */
244     private final ArraySet<String> mPrivilegedPermissionAllowlistSourcePackageNames =
245             new ArraySet<>();
246 
247     /** Lock to protect internal data access */
248     private final Object mLock = new Object();
249 
250     /** Internal connection to the package manager */
251     private final PackageManagerInternal mPackageManagerInt;
252 
253     /** Internal connection to the user manager */
254     private final UserManagerInternal mUserManagerInt;
255 
256     @GuardedBy("mLock")
257     @NonNull
258     private final DevicePermissionState mState = new DevicePermissionState();
259 
260     /** Permission controller: User space permission management */
261     private PermissionControllerManager mPermissionControllerManager;
262 
263     /** Map of OneTimePermissionUserManagers keyed by userId */
264     @GuardedBy("mLock")
265     @NonNull
266     private final SparseArray<OneTimePermissionUserManager> mOneTimePermissionUserManagers =
267             new SparseArray<>();
268 
269     /** App ops manager */
270     private final AppOpsManager mAppOpsManager;
271 
272     /**
273      * Built-in permissions. Read from system configuration files. Mapping is from
274      * UID to permission name.
275      */
276     private final SparseArray<ArraySet<String>> mSystemPermissions;
277 
278     /** Built-in group IDs given to all packages. Read from system configuration files. */
279     @NonNull
280     private final int[] mGlobalGids;
281 
282     private final HandlerThread mHandlerThread;
283     private final Handler mHandler;
284     private final Context mContext;
285     private final MetricsLogger mMetricsLogger = new MetricsLogger();
286     private final IPlatformCompat mPlatformCompat = IPlatformCompat.Stub.asInterface(
287             ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
288 
289     /** Internal storage for permissions and related settings */
290     @GuardedBy("mLock")
291     @NonNull
292     private final PermissionRegistry mRegistry = new PermissionRegistry();
293 
294     @NonNull
295     private final AttributionSourceRegistry mAttributionSourceRegistry;
296 
297     @GuardedBy("mLock")
298     @Nullable
299     private ArraySet<String> mPrivappPermissionsViolations;
300 
301     @GuardedBy("mLock")
302     private boolean mSystemReady;
303 
304     @GuardedBy("mLock")
305     private PermissionPolicyInternal mPermissionPolicyInternal;
306 
307     /**
308      * A permission backup might contain apps that are not installed. In this case we delay the
309      * restoration until the app is installed.
310      *
311      * <p>This array ({@code userId -> noDelayedBackupLeft}) is {@code true} for all the users where
312      * there is <u>no more</u> delayed backup left.
313      */
314     @GuardedBy("mLock")
315     private final SparseBooleanArray mHasNoDelayedPermBackup = new SparseBooleanArray();
316 
317     /** Listeners for permission state (granting and flags) changes */
318     @GuardedBy("mLock")
319     final private ArrayList<OnRuntimePermissionStateChangedListener>
320             mRuntimePermissionStateChangedListeners = new ArrayList<>();
321 
322     @GuardedBy("mLock")
323     private CheckPermissionDelegate mCheckPermissionDelegate;
324 
325     @NonNull
326     private final OnPermissionChangeListeners mOnPermissionChangeListeners;
327 
328     @Nullable
329     private HotwordDetectionServiceProvider mHotwordDetectionServiceProvider;
330 
331     // TODO: Take a look at the methods defined in the callback.
332     // The callback was initially created to support the split between permission
333     // manager and the package manager. However, it's started to be used for other
334     // purposes. It may make sense to keep as an abstraction, but, the methods
335     // necessary to be overridden may be different than what was initially needed
336     // for the split.
337     private final PermissionCallback mDefaultPermissionCallback = new PermissionCallback() {
338         @Override
339         public void onGidsChanged(int appId, int userId) {
340             mHandler.post(() -> killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED));
341         }
342         @Override
343         public void onPermissionGranted(int uid, int userId) {
344             mOnPermissionChangeListeners.onPermissionsChanged(uid);
345 
346             // Not critical; if this is lost, the application has to request again.
347             mPackageManagerInt.writeSettings(true);
348         }
349         @Override
350         public void onInstallPermissionGranted() {
351             mPackageManagerInt.writeSettings(true);
352         }
353         @Override
354         public void onPermissionRevoked(int uid, int userId, String reason) {
355             mOnPermissionChangeListeners.onPermissionsChanged(uid);
356 
357             // Critical; after this call the application should never have the permission
358             mPackageManagerInt.writeSettings(false);
359             final int appId = UserHandle.getAppId(uid);
360             if (reason == null) {
361                 mHandler.post(() -> killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED));
362             } else {
363                 mHandler.post(() -> killUid(appId, userId, reason));
364             }
365         }
366         @Override
367         public void onInstallPermissionRevoked() {
368             mPackageManagerInt.writeSettings(true);
369         }
370         @Override
371         public void onPermissionUpdated(int[] userIds, boolean sync) {
372             mPackageManagerInt.writePermissionSettings(userIds, !sync);
373         }
374         @Override
375         public void onInstallPermissionUpdated() {
376             mPackageManagerInt.writeSettings(true);
377         }
378         @Override
379         public void onPermissionRemoved() {
380             mPackageManagerInt.writeSettings(false);
381         }
382         public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds, boolean sync,
383                 int uid) {
384             onPermissionUpdated(updatedUserIds, sync);
385             for (int i = 0; i < updatedUserIds.length; i++) {
386                 int userUid = UserHandle.getUid(updatedUserIds[i], UserHandle.getAppId(uid));
387                 mOnPermissionChangeListeners.onPermissionsChanged(userUid);
388             }
389         }
390         public void onInstallPermissionUpdatedNotifyListener(int uid) {
391             onInstallPermissionUpdated();
392             mOnPermissionChangeListeners.onPermissionsChanged(uid);
393         }
394     };
395 
PermissionManagerService(@onNull Context context, @NonNull ArrayMap<String, FeatureInfo> availableFeatures)396     PermissionManagerService(@NonNull Context context,
397             @NonNull ArrayMap<String, FeatureInfo> availableFeatures) {
398         // The package info cache is the cache for package and permission information.
399         // Disable the package info and package permission caches locally but leave the
400         // checkPermission cache active.
401         PackageManager.invalidatePackageInfoCache();
402         PermissionManager.disablePackageNamePermissionCache();
403 
404         mContext = context;
405         mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
406         mUserManagerInt = LocalServices.getService(UserManagerInternal.class);
407         mAppOpsManager = context.getSystemService(AppOpsManager.class);
408 
409         mPrivilegedPermissionAllowlistSourcePackageNames.add(PLATFORM_PACKAGE_NAME);
410         // PackageManager.hasSystemFeature() is not used here because PackageManagerService
411         // isn't ready yet.
412         if (availableFeatures.containsKey(PackageManager.FEATURE_AUTOMOTIVE)) {
413             mPrivilegedPermissionAllowlistSourcePackageNames.add(CAR_PACKAGE_NAME);
414         }
415 
416         mHandlerThread = new ServiceThread(TAG,
417                 Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
418         mHandlerThread.start();
419         mHandler = new Handler(mHandlerThread.getLooper());
420         Watchdog.getInstance().addThread(mHandler);
421 
422         SystemConfig systemConfig = SystemConfig.getInstance();
423         mSystemPermissions = systemConfig.getSystemPermissions();
424         mGlobalGids = systemConfig.getGlobalGids();
425         mOnPermissionChangeListeners = new OnPermissionChangeListeners(FgThread.get().getLooper());
426         mAttributionSourceRegistry = new AttributionSourceRegistry(context);
427 
428         // propagate permission configuration
429         final ArrayMap<String, SystemConfig.PermissionEntry> permConfig =
430                 SystemConfig.getInstance().getPermissions();
431         synchronized (mLock) {
432             for (int i=0; i<permConfig.size(); i++) {
433                 final SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
434                 Permission bp = mRegistry.getPermission(perm.name);
435                 if (bp == null) {
436                     bp = new Permission(perm.name, "android", Permission.TYPE_CONFIG);
437                     mRegistry.addPermission(bp);
438                 }
439                 if (perm.gids != null) {
440                     bp.setGids(perm.gids, perm.perUser);
441                 }
442             }
443         }
444 
445         PermissionManagerServiceInternalImpl localService =
446                 new PermissionManagerServiceInternalImpl();
447         LocalServices.addService(PermissionManagerServiceInternal.class, localService);
448         LocalServices.addService(PermissionManagerInternal.class, localService);
449     }
450 
451     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)452     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
453         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) {
454             return;
455         }
456 
457         mContext.getSystemService(PermissionControllerManager.class).dump(fd, args);
458     }
459 
460     /**
461      * Creates and returns an initialized, internal service for use by other components.
462      * <p>
463      * The object returned is identical to the one returned by the LocalServices class using:
464      * {@code LocalServices.getService(PermissionManagerServiceInternal.class);}
465      * <p>
466      * NOTE: The external lock is temporary and should be removed. This needs to be a
467      * lock created by the permission manager itself.
468      */
469     @NonNull
create(@onNull Context context, ArrayMap<String, FeatureInfo> availableFeatures)470     public static PermissionManagerServiceInternal create(@NonNull Context context,
471             ArrayMap<String, FeatureInfo> availableFeatures) {
472         final PermissionManagerServiceInternal permMgrInt =
473                 LocalServices.getService(PermissionManagerServiceInternal.class);
474         if (permMgrInt != null) {
475             return permMgrInt;
476         }
477         PermissionManagerService permissionService =
478                 (PermissionManagerService) ServiceManager.getService("permissionmgr");
479         if (permissionService == null) {
480             permissionService = new PermissionManagerService(context, availableFeatures);
481             ServiceManager.addService("permissionmgr", permissionService);
482             ServiceManager.addService("permission_checker", new PermissionCheckerService(context));
483         }
484         return LocalServices.getService(PermissionManagerServiceInternal.class);
485     }
486 
487     /**
488      * This method should typically only be used when granting or revoking
489      * permissions, since the app may immediately restart after this call.
490      * <p>
491      * If you're doing surgery on app code/data, use {@link PackageFreezer} to
492      * guard your work against the app being relaunched.
493      */
killUid(int appId, int userId, String reason)494     public static void killUid(int appId, int userId, String reason) {
495         final long identity = Binder.clearCallingIdentity();
496         try {
497             IActivityManager am = ActivityManager.getService();
498             if (am != null) {
499                 try {
500                     am.killUidForPermissionChange(appId, userId, reason);
501                 } catch (RemoteException e) {
502                     /* ignore - same process */
503                 }
504             }
505         } finally {
506             Binder.restoreCallingIdentity(identity);
507         }
508     }
509 
510     @NonNull
getAppOpPermissionPackagesInternal(@onNull String permissionName)511     private String[] getAppOpPermissionPackagesInternal(@NonNull String permissionName) {
512         synchronized (mLock) {
513             final ArraySet<String> packageNames = mRegistry.getAppOpPermissionPackages(
514                     permissionName);
515             if (packageNames == null) {
516                 return EmptyArray.STRING;
517             }
518             return packageNames.toArray(new String[0]);
519         }
520     }
521 
522     @Override
523     @NonNull
getAllPermissionGroups( @ermissionGroupInfoFlags int flags)524     public ParceledListSlice<PermissionGroupInfo> getAllPermissionGroups(
525             @PermissionGroupInfoFlags int flags) {
526         final int callingUid = getCallingUid();
527         if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
528             return ParceledListSlice.emptyList();
529         }
530 
531         final List<PermissionGroupInfo> out = new ArrayList<>();
532         synchronized (mLock) {
533             for (ParsedPermissionGroup pg : mRegistry.getPermissionGroups()) {
534                 out.add(PackageInfoUtils.generatePermissionGroupInfo(pg, flags));
535             }
536         }
537 
538         final int callingUserId = UserHandle.getUserId(callingUid);
539         out.removeIf(it -> mPackageManagerInt.filterAppAccess(it.packageName, callingUid,
540                 callingUserId));
541         return new ParceledListSlice<>(out);
542     }
543 
544 
545     @Override
546     @Nullable
getPermissionGroupInfo(String groupName, @PermissionGroupInfoFlags int flags)547     public PermissionGroupInfo getPermissionGroupInfo(String groupName,
548             @PermissionGroupInfoFlags int flags) {
549         final int callingUid = getCallingUid();
550         if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
551             return null;
552         }
553 
554         final PermissionGroupInfo permissionGroupInfo;
555         synchronized (mLock) {
556             final ParsedPermissionGroup permissionGroup = mRegistry.getPermissionGroup(groupName);
557             if (permissionGroup == null) {
558                 return null;
559             }
560             permissionGroupInfo = PackageInfoUtils.generatePermissionGroupInfo(permissionGroup,
561                     flags);
562         }
563 
564         final int callingUserId = UserHandle.getUserId(callingUid);
565         if (mPackageManagerInt.filterAppAccess(permissionGroupInfo.packageName, callingUid,
566                 callingUserId)) {
567             EventLog.writeEvent(0x534e4554, "186113473", callingUid, groupName);
568             return null;
569         }
570         return permissionGroupInfo;
571     }
572 
573 
574     @Override
575     @Nullable
getPermissionInfo(@onNull String permName, @NonNull String opPackageName, @PermissionInfoFlags int flags)576     public PermissionInfo getPermissionInfo(@NonNull String permName, @NonNull String opPackageName,
577             @PermissionInfoFlags int flags) {
578         final int callingUid = getCallingUid();
579         if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
580             return null;
581         }
582 
583         final AndroidPackage opPackage = mPackageManagerInt.getPackage(opPackageName);
584         final int targetSdkVersion = getPermissionInfoCallingTargetSdkVersion(opPackage,
585                 callingUid);
586         final PermissionInfo permissionInfo;
587         synchronized (mLock) {
588             final Permission bp = mRegistry.getPermission(permName);
589             if (bp == null) {
590                 return null;
591             }
592             permissionInfo = bp.generatePermissionInfo(flags, targetSdkVersion);
593         }
594 
595         final int callingUserId = UserHandle.getUserId(callingUid);
596         if (mPackageManagerInt.filterAppAccess(permissionInfo.packageName, callingUid,
597                 callingUserId)) {
598             EventLog.writeEvent(0x534e4554, "183122164", callingUid, permName);
599             return null;
600         }
601         return permissionInfo;
602     }
603 
getPermissionInfoCallingTargetSdkVersion(@ullable AndroidPackage pkg, int uid)604     private int getPermissionInfoCallingTargetSdkVersion(@Nullable AndroidPackage pkg, int uid) {
605         final int appId = UserHandle.getAppId(uid);
606         if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID
607                 || appId == Process.SHELL_UID) {
608             // System sees all flags.
609             return Build.VERSION_CODES.CUR_DEVELOPMENT;
610         }
611         if (pkg == null) {
612             return Build.VERSION_CODES.CUR_DEVELOPMENT;
613         }
614         return pkg.getTargetSdkVersion();
615     }
616 
617     @Override
618     @Nullable
queryPermissionsByGroup(String groupName, @PermissionInfoFlags int flags)619     public ParceledListSlice<PermissionInfo> queryPermissionsByGroup(String groupName,
620             @PermissionInfoFlags int flags) {
621         final int callingUid = getCallingUid();
622         if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
623             return null;
624         }
625 
626         final List<PermissionInfo> out = new ArrayList<>(10);
627         synchronized (mLock) {
628             if (groupName != null && mRegistry.getPermissionGroup(groupName) == null) {
629                 return null;
630             }
631             for (Permission bp : mRegistry.getPermissions()) {
632                 if (Objects.equals(bp.getGroup(), groupName)) {
633                     out.add(bp.generatePermissionInfo(flags));
634                 }
635             }
636         }
637 
638         final int callingUserId = UserHandle.getUserId(callingUid);
639         out.removeIf(it -> mPackageManagerInt.filterAppAccess(it.packageName, callingUid,
640                 callingUserId));
641         return new ParceledListSlice<>(out);
642     }
643 
644     @Override
addPermission(PermissionInfo info, boolean async)645     public boolean addPermission(PermissionInfo info, boolean async) {
646         final int callingUid = getCallingUid();
647         if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
648             throw new SecurityException("Instant apps can't add permissions");
649         }
650         if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
651             throw new SecurityException("Label must be specified in permission");
652         }
653         final boolean added;
654         final boolean changed;
655         synchronized (mLock) {
656             final Permission tree = mRegistry.enforcePermissionTree(info.name, callingUid);
657             Permission bp = mRegistry.getPermission(info.name);
658             added = bp == null;
659             int fixedLevel = PermissionInfo.fixProtectionLevel(info.protectionLevel);
660             if (added) {
661                 enforcePermissionCapLocked(info, tree);
662                 bp = new Permission(info.name, tree.getPackageName(), Permission.TYPE_DYNAMIC);
663             } else if (!bp.isDynamic()) {
664                 throw new SecurityException("Not allowed to modify non-dynamic permission "
665                         + info.name);
666             }
667             changed = bp.addToTree(fixedLevel, info, tree);
668             if (added) {
669                 mRegistry.addPermission(bp);
670             }
671         }
672         if (changed) {
673             mPackageManagerInt.writeSettings(async);
674         }
675         return added;
676     }
677 
678     @Override
removePermission(String permName)679     public void removePermission(String permName) {
680         final int callingUid = getCallingUid();
681         if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
682             throw new SecurityException("Instant applications don't have access to this method");
683         }
684         synchronized (mLock) {
685             mRegistry.enforcePermissionTree(permName, callingUid);
686             final Permission bp = mRegistry.getPermission(permName);
687             if (bp == null) {
688                 return;
689             }
690             if (bp.isDynamic()) {
691                 // TODO: switch this back to SecurityException
692                 Slog.wtf(TAG, "Not allowed to modify non-dynamic permission "
693                         + permName);
694             }
695             mRegistry.removePermission(permName);
696         }
697         mPackageManagerInt.writeSettings(false);
698     }
699 
700     @Override
getPermissionFlags(String packageName, String permName, int userId)701     public int getPermissionFlags(String packageName, String permName, int userId) {
702         final int callingUid = getCallingUid();
703         return getPermissionFlagsInternal(packageName, permName, callingUid, userId);
704     }
705 
getPermissionFlagsInternal( String packageName, String permName, int callingUid, int userId)706     private int getPermissionFlagsInternal(
707             String packageName, String permName, int callingUid, int userId) {
708         if (!mUserManagerInt.exists(userId)) {
709             return 0;
710         }
711 
712         enforceGrantRevokeGetRuntimePermissionPermissions("getPermissionFlags");
713         enforceCrossUserPermission(callingUid, userId,
714                 true,  // requireFullPermission
715                 false, // checkShell
716                 "getPermissionFlags");
717 
718         final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
719         if (pkg == null) {
720             return 0;
721         }
722         if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
723             return 0;
724         }
725 
726         synchronized (mLock) {
727             if (mRegistry.getPermission(permName) == null) {
728                 return 0;
729             }
730 
731             final UidPermissionState uidState = getUidStateLocked(pkg, userId);
732             if (uidState == null) {
733                 Slog.e(TAG, "Missing permissions state for " + packageName + " and user " + userId);
734                 return 0;
735             }
736 
737             return uidState.getPermissionFlags(permName);
738         }
739     }
740 
741     @Override
updatePermissionFlags(String packageName, String permName, int flagMask, int flagValues, boolean checkAdjustPolicyFlagPermission, int userId)742     public void updatePermissionFlags(String packageName, String permName, int flagMask,
743             int flagValues, boolean checkAdjustPolicyFlagPermission, int userId) {
744         final int callingUid = getCallingUid();
745         boolean overridePolicy = false;
746 
747         if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID) {
748             final long callingIdentity = Binder.clearCallingIdentity();
749             try {
750                 if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0) {
751                     if (checkAdjustPolicyFlagPermission) {
752                         mContext.enforceCallingOrSelfPermission(
753                                 Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
754                                 "Need " + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY
755                                         + " to change policy flags");
756                     } else if (mPackageManagerInt.getUidTargetSdkVersion(callingUid)
757                             >= Build.VERSION_CODES.Q) {
758                         throw new IllegalArgumentException(
759                                 Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY + " needs "
760                                         + " to be checked for packages targeting "
761                                         + Build.VERSION_CODES.Q + " or later when changing policy "
762                                         + "flags");
763                     }
764                     overridePolicy = true;
765                 }
766             } finally {
767                 Binder.restoreCallingIdentity(callingIdentity);
768             }
769         }
770 
771         updatePermissionFlagsInternal(
772                 packageName, permName, flagMask, flagValues, callingUid, userId,
773                 overridePolicy, mDefaultPermissionCallback);
774     }
775 
updatePermissionFlagsInternal(String packageName, String permName, int flagMask, int flagValues, int callingUid, int userId, boolean overridePolicy, PermissionCallback callback)776     private void updatePermissionFlagsInternal(String packageName, String permName, int flagMask,
777             int flagValues, int callingUid, int userId, boolean overridePolicy,
778             PermissionCallback callback) {
779         if (PermissionManager.DEBUG_TRACE_PERMISSION_UPDATES
780                 && PermissionManager.shouldTraceGrant(packageName, permName, userId)) {
781             Log.i(TAG, "System is updating flags for " + packageName + " "
782                             + permName + " for user " + userId  + " "
783                             + DebugUtils.flagsToString(
784                                     PackageManager.class, "FLAG_PERMISSION_", flagMask)
785                             + " := "
786                             + DebugUtils.flagsToString(
787                                     PackageManager.class, "FLAG_PERMISSION_", flagValues)
788                             + " on behalf of uid " + callingUid
789                             + " " + mPackageManagerInt.getNameForUid(callingUid),
790                     new RuntimeException());
791         }
792 
793         if (!mUserManagerInt.exists(userId)) {
794             return;
795         }
796 
797         enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
798 
799         enforceCrossUserPermission(callingUid, userId,
800                 true,  // requireFullPermission
801                 true,  // checkShell
802                 "updatePermissionFlags");
803 
804         if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0 && !overridePolicy) {
805             throw new SecurityException("updatePermissionFlags requires "
806                     + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY);
807         }
808 
809         // Only the system can change these flags and nothing else.
810         if (callingUid != Process.SYSTEM_UID) {
811             flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
812             flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
813             flagMask &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
814             flagValues &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
815             flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
816             flagValues &= ~FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
817             flagValues &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
818             flagValues &= ~FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
819             flagValues &= ~PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
820         }
821 
822         final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
823         if (pkg == null) {
824             Log.e(TAG, "Unknown package: " + packageName);
825             return;
826         }
827         if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
828             throw new IllegalArgumentException("Unknown package: " + packageName);
829         }
830 
831         boolean isRequested = false;
832         // Fast path, the current package has requested the permission.
833         if (pkg.getRequestedPermissions().contains(permName)) {
834             isRequested = true;
835         }
836         if (!isRequested) {
837             // Slow path, go through all shared user packages.
838             String[] sharedUserPackageNames =
839                     mPackageManagerInt.getSharedUserPackagesForPackage(packageName, userId);
840             for (String sharedUserPackageName : sharedUserPackageNames) {
841                 AndroidPackage sharedUserPkg = mPackageManagerInt.getPackage(
842                         sharedUserPackageName);
843                 if (sharedUserPkg != null
844                         && sharedUserPkg.getRequestedPermissions().contains(permName)) {
845                     isRequested = true;
846                     break;
847                 }
848             }
849         }
850 
851         final boolean isRuntimePermission;
852         final boolean permissionUpdated;
853         synchronized (mLock) {
854             final Permission bp = mRegistry.getPermission(permName);
855             if (bp == null) {
856                 throw new IllegalArgumentException("Unknown permission: " + permName);
857             }
858 
859             isRuntimePermission = bp.isRuntime();
860 
861             final UidPermissionState uidState = getUidStateLocked(pkg, userId);
862             if (uidState == null) {
863                 Slog.e(TAG, "Missing permissions state for " + packageName + " and user " + userId);
864                 return;
865             }
866 
867             if (!uidState.hasPermissionState(permName) && !isRequested) {
868                 Log.e(TAG, "Permission " + permName + " isn't requested by package " + packageName);
869                 return;
870             }
871 
872             permissionUpdated = uidState.updatePermissionFlags(bp, flagMask, flagValues);
873         }
874 
875         if (permissionUpdated && isRuntimePermission) {
876             notifyRuntimePermissionStateChanged(packageName, userId);
877         }
878         if (permissionUpdated && callback != null) {
879             // Install and runtime permissions are stored in different places,
880             // so figure out what permission changed and persist the change.
881             if (!isRuntimePermission) {
882                 int userUid = UserHandle.getUid(userId, pkg.getUid());
883                 callback.onInstallPermissionUpdatedNotifyListener(userUid);
884             } else {
885                 callback.onPermissionUpdatedNotifyListener(new int[]{userId}, false, pkg.getUid());
886             }
887         }
888     }
889 
890     /**
891      * Update the permission flags for all packages and runtime permissions of a user in order
892      * to allow device or profile owner to remove POLICY_FIXED.
893      */
894     @Override
updatePermissionFlagsForAllApps(int flagMask, int flagValues, final int userId)895     public void updatePermissionFlagsForAllApps(int flagMask, int flagValues,
896             final int userId) {
897         final int callingUid = getCallingUid();
898         if (!mUserManagerInt.exists(userId)) {
899             return;
900         }
901 
902         enforceGrantRevokeRuntimePermissionPermissions(
903                 "updatePermissionFlagsForAllApps");
904         enforceCrossUserPermission(callingUid, userId,
905                 true,  // requireFullPermission
906                 true,  // checkShell
907                 "updatePermissionFlagsForAllApps");
908 
909         // Only the system can change system fixed flags.
910         final int effectiveFlagMask = (callingUid != Process.SYSTEM_UID)
911                 ? flagMask : flagMask & ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
912         final int effectiveFlagValues = (callingUid != Process.SYSTEM_UID)
913                 ? flagValues : flagValues & ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
914 
915         final boolean[] changed = new boolean[1];
916         mPackageManagerInt.forEachPackage(pkg -> {
917             synchronized (mLock) {
918                 final UidPermissionState uidState = getUidStateLocked(pkg, userId);
919                 if (uidState == null) {
920                     Slog.e(TAG,
921                             "Missing permissions state for " + pkg.getPackageName() + " and user "
922                                     + userId);
923                     return;
924                 }
925                 changed[0] |= uidState.updatePermissionFlagsForAllPermissions(
926                         effectiveFlagMask, effectiveFlagValues);
927             }
928             mOnPermissionChangeListeners.onPermissionsChanged(pkg.getUid());
929         });
930 
931         if (changed[0]) {
932             mPackageManagerInt.writePermissionSettings(new int[] { userId }, true);
933         }
934     }
935 
checkPermission(String pkgName, String permName, @UserIdInt int userId)936     private int checkPermission(String pkgName, String permName, @UserIdInt int userId) {
937         // Not using Objects.requireNonNull() here for compatibility reasons.
938         if (pkgName == null || permName == null) {
939             return PackageManager.PERMISSION_DENIED;
940         }
941         if (!mUserManagerInt.exists(userId)) {
942             return PackageManager.PERMISSION_DENIED;
943         }
944 
945         final CheckPermissionDelegate checkPermissionDelegate;
946         synchronized (mLock) {
947             checkPermissionDelegate = mCheckPermissionDelegate;
948         }
949         if (checkPermissionDelegate == null) {
950             return checkPermissionImpl(pkgName, permName, userId);
951         }
952         return checkPermissionDelegate.checkPermission(pkgName, permName, userId,
953                 this::checkPermissionImpl);
954     }
955 
checkPermissionImpl(String pkgName, String permName, int userId)956     private int checkPermissionImpl(String pkgName, String permName, int userId) {
957         final AndroidPackage pkg = mPackageManagerInt.getPackage(pkgName);
958         if (pkg == null) {
959             return PackageManager.PERMISSION_DENIED;
960         }
961         return checkPermissionInternal(pkg, true, permName, userId);
962     }
963 
checkPermissionInternal(@onNull AndroidPackage pkg, boolean isPackageExplicit, @NonNull String permissionName, @UserIdInt int userId)964     private int checkPermissionInternal(@NonNull AndroidPackage pkg, boolean isPackageExplicit,
965             @NonNull String permissionName, @UserIdInt int userId) {
966         final int callingUid = getCallingUid();
967         if (isPackageExplicit || pkg.getSharedUserId() == null) {
968             if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
969                 return PackageManager.PERMISSION_DENIED;
970             }
971         } else {
972             if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
973                 return PackageManager.PERMISSION_DENIED;
974             }
975         }
976 
977         final int uid = UserHandle.getUid(userId, pkg.getUid());
978         final boolean isInstantApp = mPackageManagerInt.getInstantAppPackageName(uid) != null;
979 
980         synchronized (mLock) {
981             final UidPermissionState uidState = getUidStateLocked(pkg, userId);
982             if (uidState == null) {
983                 Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
984                         + userId);
985                 return PackageManager.PERMISSION_DENIED;
986             }
987 
988             if (checkSinglePermissionInternalLocked(uidState, permissionName, isInstantApp)) {
989                 return PackageManager.PERMISSION_GRANTED;
990             }
991 
992             final String fullerPermissionName = FULLER_PERMISSION_MAP.get(permissionName);
993             if (fullerPermissionName != null && checkSinglePermissionInternalLocked(uidState,
994                     fullerPermissionName, isInstantApp)) {
995                 return PackageManager.PERMISSION_GRANTED;
996             }
997         }
998 
999         return PackageManager.PERMISSION_DENIED;
1000     }
1001 
1002     @GuardedBy("mLock")
checkSinglePermissionInternalLocked(@onNull UidPermissionState uidState, @NonNull String permissionName, boolean isInstantApp)1003     private boolean checkSinglePermissionInternalLocked(@NonNull UidPermissionState uidState,
1004             @NonNull String permissionName, boolean isInstantApp) {
1005         if (!uidState.isPermissionGranted(permissionName)) {
1006             return false;
1007         }
1008 
1009         if (isInstantApp) {
1010             final Permission permission = mRegistry.getPermission(permissionName);
1011             return permission != null && permission.isInstant();
1012         }
1013 
1014         return true;
1015     }
1016 
checkUidPermission(int uid, String permName)1017     private int checkUidPermission(int uid, String permName) {
1018         // Not using Objects.requireNonNull() here for compatibility reasons.
1019         if (permName == null) {
1020             return PackageManager.PERMISSION_DENIED;
1021         }
1022         final int userId = UserHandle.getUserId(uid);
1023         if (!mUserManagerInt.exists(userId)) {
1024             return PackageManager.PERMISSION_DENIED;
1025         }
1026 
1027         final CheckPermissionDelegate checkPermissionDelegate;
1028         synchronized (mLock) {
1029             checkPermissionDelegate = mCheckPermissionDelegate;
1030         }
1031         if (checkPermissionDelegate == null)  {
1032             return checkUidPermissionImpl(uid, permName);
1033         }
1034         return checkPermissionDelegate.checkUidPermission(uid, permName,
1035                 this::checkUidPermissionImpl);
1036     }
1037 
checkUidPermissionImpl(int uid, String permName)1038     private int checkUidPermissionImpl(int uid, String permName) {
1039         final AndroidPackage pkg = mPackageManagerInt.getPackage(uid);
1040         return checkUidPermissionInternal(pkg, uid, permName);
1041     }
1042 
1043     /**
1044      * Checks whether or not the given package has been granted the specified
1045      * permission. If the given package is {@code null}, we instead check the
1046      * system permissions for the given UID.
1047      *
1048      * @see SystemConfig#getSystemPermissions()
1049      */
checkUidPermissionInternal(@ullable AndroidPackage pkg, int uid, @NonNull String permissionName)1050     private int checkUidPermissionInternal(@Nullable AndroidPackage pkg, int uid,
1051             @NonNull String permissionName) {
1052         if (pkg != null) {
1053             final int userId = UserHandle.getUserId(uid);
1054             return checkPermissionInternal(pkg, false, permissionName, userId);
1055         }
1056 
1057         synchronized (mLock) {
1058             if (checkSingleUidPermissionInternalLocked(uid, permissionName)) {
1059                 return PackageManager.PERMISSION_GRANTED;
1060             }
1061 
1062             final String fullerPermissionName = FULLER_PERMISSION_MAP.get(permissionName);
1063             if (fullerPermissionName != null
1064                     && checkSingleUidPermissionInternalLocked(uid, fullerPermissionName)) {
1065                 return PackageManager.PERMISSION_GRANTED;
1066             }
1067         }
1068 
1069         return PackageManager.PERMISSION_DENIED;
1070     }
1071 
1072     @GuardedBy("mLock")
checkSingleUidPermissionInternalLocked(int uid, @NonNull String permissionName)1073     private boolean checkSingleUidPermissionInternalLocked(int uid,
1074             @NonNull String permissionName) {
1075         ArraySet<String> permissions = mSystemPermissions.get(uid);
1076         return permissions != null && permissions.contains(permissionName);
1077     }
1078 
1079     @Override
addOnPermissionsChangeListener(IOnPermissionsChangeListener listener)1080     public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
1081         mContext.enforceCallingOrSelfPermission(
1082                 Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS,
1083                 "addOnPermissionsChangeListener");
1084 
1085         mOnPermissionChangeListeners.addListener(listener);
1086     }
1087 
1088     @Override
removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener)1089     public void removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
1090         if (mPackageManagerInt.getInstantAppPackageName(Binder.getCallingUid()) != null) {
1091             throw new SecurityException("Instant applications don't have access to this method");
1092         }
1093         mOnPermissionChangeListeners.removeListener(listener);
1094     }
1095 
1096     @Nullable
1097     @Override
getAllowlistedRestrictedPermissions(@onNull String packageName, @PermissionWhitelistFlags int flags, @UserIdInt int userId)1098     public List<String> getAllowlistedRestrictedPermissions(@NonNull String packageName,
1099             @PermissionWhitelistFlags int flags, @UserIdInt int userId) {
1100         Objects.requireNonNull(packageName);
1101         Preconditions.checkFlagsArgument(flags,
1102                 PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
1103                         | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
1104                         | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
1105         Preconditions.checkArgumentNonNegative(userId, null);
1106 
1107         if (UserHandle.getCallingUserId() != userId) {
1108             mContext.enforceCallingOrSelfPermission(
1109                     android.Manifest.permission.INTERACT_ACROSS_USERS,
1110                     "getAllowlistedRestrictedPermissions for user " + userId);
1111         }
1112 
1113         final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
1114         if (pkg == null) {
1115             return null;
1116         }
1117 
1118         final int callingUid = Binder.getCallingUid();
1119         if (mPackageManagerInt.filterAppAccess(pkg, callingUid, UserHandle.getCallingUserId())) {
1120             return null;
1121         }
1122         final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
1123                 Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
1124                         == PackageManager.PERMISSION_GRANTED;
1125         final boolean isCallerInstallerOnRecord =
1126                 mPackageManagerInt.isCallerInstallerOfRecord(pkg, callingUid);
1127 
1128         if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0
1129                 && !isCallerPrivileged) {
1130             throw new SecurityException("Querying system allowlist requires "
1131                     + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
1132         }
1133 
1134         if ((flags & (PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
1135                 | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER)) != 0) {
1136             if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
1137                 throw new SecurityException("Querying upgrade or installer allowlist"
1138                         + " requires being installer on record or "
1139                         + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
1140             }
1141         }
1142 
1143         final long identity = Binder.clearCallingIdentity();
1144         try {
1145             return getAllowlistedRestrictedPermissionsInternal(pkg, flags, userId);
1146         } finally {
1147             Binder.restoreCallingIdentity(identity);
1148         }
1149     }
1150 
1151     @Nullable
getAllowlistedRestrictedPermissionsInternal(@onNull AndroidPackage pkg, @PermissionWhitelistFlags int flags, @UserIdInt int userId)1152     private List<String> getAllowlistedRestrictedPermissionsInternal(@NonNull AndroidPackage pkg,
1153             @PermissionWhitelistFlags int flags, @UserIdInt int userId) {
1154         synchronized (mLock) {
1155             final UidPermissionState uidState = getUidStateLocked(pkg, userId);
1156             if (uidState == null) {
1157                 Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
1158                         + userId);
1159                 return null;
1160             }
1161 
1162             int queryFlags = 0;
1163             if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0) {
1164                 queryFlags |= FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
1165             }
1166             if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE) != 0) {
1167                 queryFlags |= FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
1168             }
1169             if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
1170                 queryFlags |= FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
1171             }
1172 
1173             ArrayList<String> allowlistedPermissions = null;
1174 
1175             final int permissionCount = ArrayUtils.size(pkg.getRequestedPermissions());
1176             for (int i = 0; i < permissionCount; i++) {
1177                 final String permissionName = pkg.getRequestedPermissions().get(i);
1178                 final int currentFlags =
1179                         uidState.getPermissionFlags(permissionName);
1180                 if ((currentFlags & queryFlags) != 0) {
1181                     if (allowlistedPermissions == null) {
1182                         allowlistedPermissions = new ArrayList<>();
1183                     }
1184                     allowlistedPermissions.add(permissionName);
1185                 }
1186             }
1187 
1188             return allowlistedPermissions;
1189         }
1190     }
1191 
1192     @Override
addAllowlistedRestrictedPermission(@onNull String packageName, @NonNull String permName, @PermissionWhitelistFlags int flags, @UserIdInt int userId)1193     public boolean addAllowlistedRestrictedPermission(@NonNull String packageName,
1194             @NonNull String permName, @PermissionWhitelistFlags int flags,
1195             @UserIdInt int userId) {
1196         // Other argument checks are done in get/setAllowlistedRestrictedPermissions
1197         Objects.requireNonNull(permName);
1198 
1199         if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permName)) {
1200             return false;
1201         }
1202 
1203         List<String> permissions =
1204                 getAllowlistedRestrictedPermissions(packageName, flags, userId);
1205         if (permissions == null) {
1206             permissions = new ArrayList<>(1);
1207         }
1208         if (permissions.indexOf(permName) < 0) {
1209             permissions.add(permName);
1210             return setAllowlistedRestrictedPermissions(packageName, permissions,
1211                     flags, userId);
1212         }
1213         return false;
1214     }
1215 
checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission( @onNull String permName)1216     private boolean checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(
1217             @NonNull String permName) {
1218         final boolean isImmutablyRestrictedPermission;
1219         synchronized (mLock) {
1220             final Permission bp = mRegistry.getPermission(permName);
1221             if (bp == null) {
1222                 Slog.w(TAG, "No such permissions: " + permName);
1223                 return false;
1224             }
1225             isImmutablyRestrictedPermission = bp.isHardOrSoftRestricted()
1226                     && bp.isImmutablyRestricted();
1227         }
1228         if (isImmutablyRestrictedPermission && mContext.checkCallingOrSelfPermission(
1229                 Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
1230                 != PackageManager.PERMISSION_GRANTED) {
1231             throw new SecurityException("Cannot modify allowlisting of an immutably "
1232                     + "restricted permission: " + permName);
1233         }
1234         return true;
1235     }
1236 
1237     @Override
removeAllowlistedRestrictedPermission(@onNull String packageName, @NonNull String permName, @PermissionWhitelistFlags int flags, @UserIdInt int userId)1238     public boolean removeAllowlistedRestrictedPermission(@NonNull String packageName,
1239             @NonNull String permName, @PermissionWhitelistFlags int flags,
1240             @UserIdInt int userId) {
1241         // Other argument checks are done in get/setAllowlistedRestrictedPermissions
1242         Objects.requireNonNull(permName);
1243 
1244         if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permName)) {
1245             return false;
1246         }
1247 
1248         final List<String> permissions =
1249                 getAllowlistedRestrictedPermissions(packageName, flags, userId);
1250         if (permissions != null && permissions.remove(permName)) {
1251             return setAllowlistedRestrictedPermissions(packageName, permissions,
1252                     flags, userId);
1253         }
1254         return false;
1255     }
1256 
setAllowlistedRestrictedPermissions(@onNull String packageName, @Nullable List<String> permissions, @PermissionWhitelistFlags int flags, @UserIdInt int userId)1257     private boolean setAllowlistedRestrictedPermissions(@NonNull String packageName,
1258             @Nullable List<String> permissions, @PermissionWhitelistFlags int flags,
1259             @UserIdInt int userId) {
1260         Objects.requireNonNull(packageName);
1261         Preconditions.checkFlagsArgument(flags,
1262                 PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
1263                         | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
1264                         | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
1265         Preconditions.checkArgument(Integer.bitCount(flags) == 1);
1266         Preconditions.checkArgumentNonNegative(userId, null);
1267 
1268         if (UserHandle.getCallingUserId() != userId) {
1269             mContext.enforceCallingOrSelfPermission(
1270                     Manifest.permission.INTERACT_ACROSS_USERS,
1271                     "setAllowlistedRestrictedPermissions for user " + userId);
1272         }
1273 
1274         final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
1275         if (pkg == null) {
1276             return false;
1277         }
1278 
1279         final int callingUid = Binder.getCallingUid();
1280         if (mPackageManagerInt.filterAppAccess(pkg, callingUid, UserHandle.getCallingUserId())) {
1281             return false;
1282         }
1283 
1284         final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
1285                 Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
1286                         == PackageManager.PERMISSION_GRANTED;
1287         final boolean isCallerInstallerOnRecord =
1288                 mPackageManagerInt.isCallerInstallerOfRecord(pkg, callingUid);
1289 
1290         if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0 && !isCallerPrivileged) {
1291             throw new SecurityException("Modifying system allowlist requires "
1292                     + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
1293         }
1294 
1295         if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE) != 0) {
1296             if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
1297                 throw new SecurityException("Modifying upgrade allowlist requires"
1298                         + " being installer on record or "
1299                         + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
1300             }
1301             final List<String> allowlistedPermissions =
1302                     getAllowlistedRestrictedPermissions(pkg.getPackageName(), flags, userId);
1303             if (permissions == null || permissions.isEmpty()) {
1304                 if (allowlistedPermissions == null || allowlistedPermissions.isEmpty()) {
1305                     return true;
1306                 }
1307             } else {
1308                 // Only the system can add and remove while the installer can only remove.
1309                 final int permissionCount = permissions.size();
1310                 for (int i = 0; i < permissionCount; i++) {
1311                     if ((allowlistedPermissions == null
1312                             || !allowlistedPermissions.contains(permissions.get(i)))
1313                             && !isCallerPrivileged) {
1314                         throw new SecurityException("Adding to upgrade allowlist requires"
1315                                 + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
1316                     }
1317                 }
1318             }
1319 
1320             if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
1321                 if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
1322                     throw new SecurityException("Modifying installer allowlist requires"
1323                             + " being installer on record or "
1324                             + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
1325                 }
1326             }
1327         }
1328 
1329         final long identity = Binder.clearCallingIdentity();
1330         try {
1331             setAllowlistedRestrictedPermissionsInternal(pkg, permissions, flags, userId);
1332         } finally {
1333             Binder.restoreCallingIdentity(identity);
1334         }
1335 
1336         return true;
1337     }
1338 
1339     @Override
setAutoRevokeExempted( @onNull String packageName, boolean exempted, int userId)1340     public boolean setAutoRevokeExempted(
1341             @NonNull String packageName, boolean exempted, int userId) {
1342         Objects.requireNonNull(packageName);
1343 
1344         final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
1345         final int callingUid = Binder.getCallingUid();
1346 
1347         if (!checkAutoRevokeAccess(pkg, callingUid)) {
1348             return false;
1349         }
1350 
1351         return setAutoRevokeExemptedInternal(pkg, exempted, userId);
1352     }
1353 
setAutoRevokeExemptedInternal(@onNull AndroidPackage pkg, boolean exempted, @UserIdInt int userId)1354     private boolean setAutoRevokeExemptedInternal(@NonNull AndroidPackage pkg, boolean exempted,
1355             @UserIdInt int userId) {
1356         final int packageUid = UserHandle.getUid(userId, pkg.getUid());
1357         if (mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_AUTO_REVOKE_MANAGED_BY_INSTALLER,
1358                 packageUid, pkg.getPackageName()) != MODE_ALLOWED) {
1359             // Allowlist user set - don't override
1360             return false;
1361         }
1362 
1363         final long identity = Binder.clearCallingIdentity();
1364         try {
1365             mAppOpsManager.setMode(AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, packageUid,
1366                     pkg.getPackageName(), exempted ? MODE_IGNORED : MODE_ALLOWED);
1367         } finally {
1368             Binder.restoreCallingIdentity(identity);
1369         }
1370         return true;
1371     }
1372 
checkAutoRevokeAccess(AndroidPackage pkg, int callingUid)1373     private boolean checkAutoRevokeAccess(AndroidPackage pkg, int callingUid) {
1374         if (pkg == null) {
1375             return false;
1376         }
1377 
1378         final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
1379                 Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS)
1380                 == PackageManager.PERMISSION_GRANTED;
1381         final boolean isCallerInstallerOnRecord =
1382                 mPackageManagerInt.isCallerInstallerOfRecord(pkg, callingUid);
1383 
1384         if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
1385             throw new SecurityException("Caller must either hold "
1386                     + Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS
1387                     + " or be the installer on record");
1388         }
1389         return true;
1390     }
1391 
1392     @Override
isAutoRevokeExempted(@onNull String packageName, int userId)1393     public boolean isAutoRevokeExempted(@NonNull String packageName, int userId) {
1394         Objects.requireNonNull(packageName);
1395 
1396         final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
1397         final int callingUid = Binder.getCallingUid();
1398         if (mPackageManagerInt.filterAppAccess(packageName, callingUid, userId)) {
1399             return false;
1400         }
1401 
1402         if (!checkAutoRevokeAccess(pkg, callingUid)) {
1403             return false;
1404         }
1405 
1406         final int packageUid = UserHandle.getUid(userId, pkg.getUid());
1407 
1408         final long identity = Binder.clearCallingIdentity();
1409         try {
1410             return mAppOpsManager.checkOpNoThrow(
1411                     AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, packageUid, packageName)
1412                     == MODE_IGNORED;
1413         } finally {
1414             Binder.restoreCallingIdentity(identity);
1415         }
1416     }
1417 
1418     @Override
grantRuntimePermission(String packageName, String permName, final int userId)1419     public void grantRuntimePermission(String packageName, String permName, final int userId) {
1420         final int callingUid = Binder.getCallingUid();
1421         final boolean overridePolicy =
1422                 checkUidPermission(callingUid, ADJUST_RUNTIME_PERMISSIONS_POLICY)
1423                         == PackageManager.PERMISSION_GRANTED;
1424 
1425         grantRuntimePermissionInternal(packageName, permName, overridePolicy,
1426                 callingUid, userId, mDefaultPermissionCallback);
1427     }
1428 
grantRuntimePermissionInternal(String packageName, String permName, boolean overridePolicy, int callingUid, final int userId, PermissionCallback callback)1429     private void grantRuntimePermissionInternal(String packageName, String permName,
1430             boolean overridePolicy, int callingUid, final int userId, PermissionCallback callback) {
1431         if (PermissionManager.DEBUG_TRACE_GRANTS
1432                 && PermissionManager.shouldTraceGrant(packageName, permName, userId)) {
1433             Log.i(PermissionManager.LOG_TAG_TRACE_GRANTS, "System is granting " + packageName + " "
1434                     + permName + " for user " + userId + " on behalf of uid " + callingUid
1435                     + " " + mPackageManagerInt.getNameForUid(callingUid),
1436                     new RuntimeException());
1437         }
1438         if (!mUserManagerInt.exists(userId)) {
1439             Log.e(TAG, "No such user:" + userId);
1440             return;
1441         }
1442 
1443         mContext.enforceCallingOrSelfPermission(
1444                 android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
1445                 "grantRuntimePermission");
1446 
1447         enforceCrossUserPermission(callingUid, userId,
1448                 true,  // requireFullPermission
1449                 true,  // checkShell
1450                 "grantRuntimePermission");
1451 
1452         final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
1453         final PackageSetting ps = mPackageManagerInt.getPackageSetting(packageName);
1454         if (pkg == null || ps == null) {
1455             Log.e(TAG, "Unknown package: " + packageName);
1456             return;
1457         }
1458         if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
1459             throw new IllegalArgumentException("Unknown package: " + packageName);
1460         }
1461 
1462         final boolean isRolePermission;
1463         final boolean isSoftRestrictedPermission;
1464         synchronized (mLock) {
1465             final Permission permission = mRegistry.getPermission(permName);
1466             if (permission == null) {
1467                 throw new IllegalArgumentException("Unknown permission: " + permName);
1468             }
1469             isRolePermission = permission.isRole();
1470             isSoftRestrictedPermission = permission.isSoftRestricted();
1471         }
1472         final boolean mayGrantRolePermission = isRolePermission
1473                 && mayManageRolePermission(callingUid);
1474         final boolean mayGrantSoftRestrictedPermission = isSoftRestrictedPermission
1475                 && SoftRestrictedPermissionPolicy.forPermission(mContext,
1476                         pkg.toAppInfoWithoutState(), pkg, UserHandle.of(userId), permName)
1477                         .mayGrantPermission();
1478 
1479         final boolean isRuntimePermission;
1480         final boolean permissionHasGids;
1481         synchronized (mLock) {
1482             final Permission bp = mRegistry.getPermission(permName);
1483             if (bp == null) {
1484                 throw new IllegalArgumentException("Unknown permission: " + permName);
1485             }
1486 
1487             isRuntimePermission = bp.isRuntime();
1488             permissionHasGids = bp.hasGids();
1489             if (isRuntimePermission || bp.isDevelopment()) {
1490                 // Good.
1491             } else if (bp.isRole()) {
1492                 if (!mayGrantRolePermission) {
1493                     throw new SecurityException("Permission " + permName + " is managed by role");
1494                 }
1495             } else {
1496                 throw new SecurityException("Permission " + permName + " requested by "
1497                         + pkg.getPackageName() + " is not a changeable permission type");
1498             }
1499 
1500             final UidPermissionState uidState = getUidStateLocked(pkg, userId);
1501             if (uidState == null) {
1502                 Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
1503                         + userId);
1504                 return;
1505             }
1506 
1507             if (!(uidState.hasPermissionState(permName)
1508                     || pkg.getRequestedPermissions().contains(permName))) {
1509                 throw new SecurityException("Package " + pkg.getPackageName()
1510                         + " has not requested permission " + permName);
1511             }
1512 
1513             // If a permission review is required for legacy apps we represent
1514             // their permissions as always granted runtime ones since we need
1515             // to keep the review required permission flag per user while an
1516             // install permission's state is shared across all users.
1517             if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M && bp.isRuntime()) {
1518                 return;
1519             }
1520 
1521             final int flags = uidState.getPermissionFlags(permName);
1522             if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
1523                 Log.e(TAG, "Cannot grant system fixed permission "
1524                         + permName + " for package " + packageName);
1525                 return;
1526             }
1527             if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
1528                 Log.e(TAG, "Cannot grant policy fixed permission "
1529                         + permName + " for package " + packageName);
1530                 return;
1531             }
1532 
1533             if (bp.isHardRestricted()
1534                     && (flags & PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) == 0) {
1535                 Log.e(TAG, "Cannot grant hard restricted non-exempt permission "
1536                         + permName + " for package " + packageName);
1537                 return;
1538             }
1539 
1540             if (bp.isSoftRestricted() && !mayGrantSoftRestrictedPermission) {
1541                 Log.e(TAG, "Cannot grant soft restricted permission " + permName + " for package "
1542                         + packageName);
1543                 return;
1544             }
1545 
1546             if (bp.isDevelopment() || bp.isRole()) {
1547                 // Development permissions must be handled specially, since they are not
1548                 // normal runtime permissions.  For now they apply to all users.
1549                 // TODO(zhanghai): We are breaking the behavior above by making all permission state
1550                 //  per-user. It isn't documented behavior and relatively rarely used anyway.
1551                 if (!uidState.grantPermission(bp)) {
1552                     return;
1553                 }
1554             } else {
1555                 if (ps.getInstantApp(userId) && !bp.isInstant()) {
1556                     throw new SecurityException("Cannot grant non-ephemeral permission" + permName
1557                             + " for package " + packageName);
1558                 }
1559 
1560                 if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M) {
1561                     Slog.w(TAG, "Cannot grant runtime permission to a legacy app");
1562                     return;
1563                 }
1564 
1565                 if (!uidState.grantPermission(bp)) {
1566                     return;
1567                 }
1568             }
1569         }
1570 
1571         if (isRuntimePermission) {
1572             logPermission(MetricsEvent.ACTION_PERMISSION_GRANTED, permName, packageName);
1573         }
1574 
1575         final int uid = UserHandle.getUid(userId, pkg.getUid());
1576         if (callback != null) {
1577             if (isRuntimePermission) {
1578                 callback.onPermissionGranted(uid, userId);
1579             } else {
1580                 callback.onInstallPermissionGranted();
1581             }
1582             if (permissionHasGids) {
1583                 callback.onGidsChanged(UserHandle.getAppId(pkg.getUid()), userId);
1584             }
1585         }
1586 
1587         if (isRuntimePermission) {
1588             notifyRuntimePermissionStateChanged(packageName, userId);
1589         }
1590     }
1591 
1592     @Override
revokeRuntimePermission(String packageName, String permName, int userId, String reason)1593     public void revokeRuntimePermission(String packageName, String permName, int userId,
1594             String reason) {
1595         final int callingUid = Binder.getCallingUid();
1596         final boolean overridePolicy =
1597                 checkUidPermission(callingUid, ADJUST_RUNTIME_PERMISSIONS_POLICY)
1598                         == PackageManager.PERMISSION_GRANTED;
1599 
1600         revokeRuntimePermissionInternal(packageName, permName, overridePolicy, callingUid, userId,
1601                 reason, mDefaultPermissionCallback);
1602     }
1603 
revokeRuntimePermissionInternal(String packageName, String permName, boolean overridePolicy, int callingUid, final int userId, String reason, PermissionCallback callback)1604     private void revokeRuntimePermissionInternal(String packageName, String permName,
1605             boolean overridePolicy, int callingUid, final int userId, String reason,
1606             PermissionCallback callback) {
1607         if (PermissionManager.DEBUG_TRACE_PERMISSION_UPDATES
1608                 && PermissionManager.shouldTraceGrant(packageName, permName, userId)) {
1609             Log.i(TAG, "System is revoking " + packageName + " "
1610                             + permName + " for user " + userId + " on behalf of uid " + callingUid
1611                             + " " + mPackageManagerInt.getNameForUid(callingUid),
1612                     new RuntimeException());
1613         }
1614         if (!mUserManagerInt.exists(userId)) {
1615             Log.e(TAG, "No such user:" + userId);
1616             return;
1617         }
1618 
1619         mContext.enforceCallingOrSelfPermission(
1620                 android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
1621                 "revokeRuntimePermission");
1622 
1623         enforceCrossUserPermission(callingUid, userId,
1624                 true,  // requireFullPermission
1625                 true,  // checkShell
1626                 "revokeRuntimePermission");
1627 
1628         final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
1629         if (pkg == null) {
1630             Log.e(TAG, "Unknown package: " + packageName);
1631             return;
1632         }
1633         if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
1634             throw new IllegalArgumentException("Unknown package: " + packageName);
1635         }
1636 
1637         final boolean isRolePermission;
1638         synchronized (mLock) {
1639             final Permission permission = mRegistry.getPermission(permName);
1640             if (permission == null) {
1641                 throw new IllegalArgumentException("Unknown permission: " + permName);
1642             }
1643             isRolePermission = permission.isRole();
1644         }
1645         final boolean mayRevokeRolePermission = isRolePermission
1646                 && mayManageRolePermission(callingUid);
1647 
1648         final boolean isRuntimePermission;
1649         synchronized (mLock) {
1650             final Permission bp = mRegistry.getPermission(permName);
1651             if (bp == null) {
1652                 throw new IllegalArgumentException("Unknown permission: " + permName);
1653             }
1654 
1655             isRuntimePermission = bp.isRuntime();
1656             if (isRuntimePermission || bp.isDevelopment()) {
1657                 // Good.
1658             } else if (bp.isRole()) {
1659                 if (!mayRevokeRolePermission) {
1660                     throw new SecurityException("Permission " + permName + " is managed by role");
1661                 }
1662             } else {
1663                 throw new SecurityException("Permission " + permName + " requested by "
1664                         + pkg.getPackageName() + " is not a changeable permission type");
1665             }
1666 
1667             final UidPermissionState uidState = getUidStateLocked(pkg, userId);
1668             if (uidState == null) {
1669                 Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
1670                         + userId);
1671                 return;
1672             }
1673 
1674             if (!(uidState.hasPermissionState(permName)
1675                     || pkg.getRequestedPermissions().contains(permName))) {
1676                 throw new SecurityException("Package " + pkg.getPackageName()
1677                         + " has not requested permission " + permName);
1678             }
1679 
1680             // If a permission review is required for legacy apps we represent
1681             // their permissions as always granted runtime ones since we need
1682             // to keep the review required permission flag per user while an
1683             // install permission's state is shared across all users.
1684             if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M && bp.isRuntime()) {
1685                 return;
1686             }
1687 
1688             final int flags = uidState.getPermissionFlags(permName);
1689             // Only the system may revoke SYSTEM_FIXED permissions.
1690             if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0
1691                     && UserHandle.getCallingAppId() != Process.SYSTEM_UID) {
1692                 throw new SecurityException("Non-System UID cannot revoke system fixed permission "
1693                         + permName + " for package " + packageName);
1694             }
1695             if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
1696                 throw new SecurityException("Cannot revoke policy fixed permission "
1697                         + permName + " for package " + packageName);
1698             }
1699 
1700             // Development permissions must be handled specially, since they are not
1701             // normal runtime permissions.  For now they apply to all users.
1702             // TODO(zhanghai): We are breaking the behavior above by making all permission state
1703             //  per-user. It isn't documented behavior and relatively rarely used anyway.
1704             if (!uidState.revokePermission(bp)) {
1705                 return;
1706             }
1707         }
1708 
1709         if (isRuntimePermission) {
1710             logPermission(MetricsEvent.ACTION_PERMISSION_REVOKED, permName, packageName);
1711         }
1712 
1713         if (callback != null) {
1714             if (isRuntimePermission) {
1715                 callback.onPermissionRevoked(UserHandle.getUid(userId, pkg.getUid()), userId,
1716                         reason);
1717             } else {
1718                 mDefaultPermissionCallback.onInstallPermissionRevoked();
1719             }
1720         }
1721 
1722         if (isRuntimePermission) {
1723             notifyRuntimePermissionStateChanged(packageName, userId);
1724         }
1725     }
1726 
mayManageRolePermission(int uid)1727     private boolean mayManageRolePermission(int uid) {
1728         final PackageManager packageManager = mContext.getPackageManager();
1729         final String[] packageNames = packageManager.getPackagesForUid(uid);
1730         if (packageNames == null) {
1731             return false;
1732         }
1733         final String permissionControllerPackageName =
1734                 packageManager.getPermissionControllerPackageName();
1735         return Arrays.asList(packageNames).contains(permissionControllerPackageName);
1736     }
1737 
1738     /**
1739      * Reverts user permission state changes (permissions and flags).
1740      *
1741      * @param pkg The package for which to reset.
1742      * @param userId The device user for which to do a reset.
1743      */
resetRuntimePermissionsInternal(@onNull AndroidPackage pkg, @UserIdInt int userId)1744     private void resetRuntimePermissionsInternal(@NonNull AndroidPackage pkg,
1745             @UserIdInt int userId) {
1746         final String packageName = pkg.getPackageName();
1747 
1748         // These are flags that can change base on user actions.
1749         final int userSettableMask = FLAG_PERMISSION_USER_SET
1750                 | FLAG_PERMISSION_USER_FIXED
1751                 | FLAG_PERMISSION_REVOKED_COMPAT
1752                 | FLAG_PERMISSION_REVIEW_REQUIRED
1753                 | FLAG_PERMISSION_ONE_TIME
1754                 | FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY;
1755 
1756         final int policyOrSystemFlags = FLAG_PERMISSION_SYSTEM_FIXED
1757                 | FLAG_PERMISSION_POLICY_FIXED;
1758 
1759         // Delay and combine non-async permission callbacks
1760         final int permissionCount = ArrayUtils.size(pkg.getRequestedPermissions());
1761         final boolean[] permissionRemoved = new boolean[1];
1762         final ArraySet<Long> revokedPermissions = new ArraySet<>();
1763         final IntArray syncUpdatedUsers = new IntArray(permissionCount);
1764         final IntArray asyncUpdatedUsers = new IntArray(permissionCount);
1765 
1766         PermissionCallback delayingPermCallback = new PermissionCallback() {
1767             public void onGidsChanged(int appId, int userId) {
1768                 mDefaultPermissionCallback.onGidsChanged(appId, userId);
1769             }
1770 
1771             public void onPermissionChanged() {
1772                 mDefaultPermissionCallback.onPermissionChanged();
1773             }
1774 
1775             public void onPermissionGranted(int uid, int userId) {
1776                 mDefaultPermissionCallback.onPermissionGranted(uid, userId);
1777             }
1778 
1779             public void onInstallPermissionGranted() {
1780                 mDefaultPermissionCallback.onInstallPermissionGranted();
1781             }
1782 
1783             public void onPermissionRevoked(int uid, int userId, String reason) {
1784                 revokedPermissions.add(IntPair.of(uid, userId));
1785 
1786                 syncUpdatedUsers.add(userId);
1787             }
1788 
1789             public void onInstallPermissionRevoked() {
1790                 mDefaultPermissionCallback.onInstallPermissionRevoked();
1791             }
1792 
1793             public void onPermissionUpdated(int[] updatedUserIds, boolean sync) {
1794                 for (int userId : updatedUserIds) {
1795                     if (sync) {
1796                         syncUpdatedUsers.add(userId);
1797                         asyncUpdatedUsers.remove(userId);
1798                     } else {
1799                         // Don't override sync=true by sync=false
1800                         if (syncUpdatedUsers.indexOf(userId) == -1) {
1801                             asyncUpdatedUsers.add(userId);
1802                         }
1803                     }
1804                 }
1805             }
1806 
1807             public void onPermissionRemoved() {
1808                 permissionRemoved[0] = true;
1809             }
1810 
1811             public void onInstallPermissionUpdated() {
1812                 mDefaultPermissionCallback.onInstallPermissionUpdated();
1813             }
1814 
1815             public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds,
1816                     boolean sync, int uid) {
1817                 onPermissionUpdated(updatedUserIds, sync);
1818                 mOnPermissionChangeListeners.onPermissionsChanged(uid);
1819             }
1820 
1821             public void onInstallPermissionUpdatedNotifyListener(int uid) {
1822                 mDefaultPermissionCallback.onInstallPermissionUpdatedNotifyListener(uid);
1823             }
1824         };
1825 
1826         for (int i = 0; i < permissionCount; i++) {
1827             final String permName = pkg.getRequestedPermissions().get(i);
1828 
1829             final boolean isRuntimePermission;
1830             synchronized (mLock) {
1831                 final Permission permission = mRegistry.getPermission(permName);
1832                 if (permission == null) {
1833                     continue;
1834                 }
1835 
1836                 if (permission.isRemoved()) {
1837                     continue;
1838                 }
1839                 isRuntimePermission = permission.isRuntime();
1840             }
1841 
1842             // If shared user we just reset the state to which only this app contributed.
1843             final String[] pkgNames = mPackageManagerInt.getSharedUserPackagesForPackage(
1844                     pkg.getPackageName(), userId);
1845             if (pkgNames.length > 0) {
1846                 boolean used = false;
1847                 for (String sharedPkgName : pkgNames) {
1848                     final AndroidPackage sharedPkg =
1849                             mPackageManagerInt.getPackage(sharedPkgName);
1850                     if (sharedPkg != null && !sharedPkg.getPackageName().equals(packageName)
1851                             && sharedPkg.getRequestedPermissions().contains(permName)) {
1852                         used = true;
1853                         break;
1854                     }
1855                 }
1856                 if (used) {
1857                     continue;
1858                 }
1859             }
1860 
1861             final int oldFlags =
1862                     getPermissionFlagsInternal(packageName, permName, Process.SYSTEM_UID, userId);
1863 
1864             // Always clear the user settable flags.
1865             // If permission review is enabled and this is a legacy app, mark the
1866             // permission as requiring a review as this is the initial state.
1867             final int uid = mPackageManagerInt.getPackageUid(packageName, 0, userId);
1868             final int targetSdk = mPackageManagerInt.getUidTargetSdkVersion(uid);
1869             final int flags = (targetSdk < Build.VERSION_CODES.M && isRuntimePermission)
1870                     ? FLAG_PERMISSION_REVIEW_REQUIRED | FLAG_PERMISSION_REVOKED_COMPAT
1871                     : 0;
1872 
1873             updatePermissionFlagsInternal(
1874                     packageName, permName, userSettableMask, flags, Process.SYSTEM_UID, userId,
1875                     false, delayingPermCallback);
1876 
1877             // Below is only runtime permission handling.
1878             if (!isRuntimePermission) {
1879                 continue;
1880             }
1881 
1882             // Never clobber system or policy.
1883             if ((oldFlags & policyOrSystemFlags) != 0) {
1884                 continue;
1885             }
1886 
1887             // If this permission was granted by default or role, make sure it is.
1888             if ((oldFlags & FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0
1889                     || (oldFlags & FLAG_PERMISSION_GRANTED_BY_ROLE) != 0) {
1890                 // PermissionPolicyService will handle the app op for runtime permissions later.
1891                 grantRuntimePermissionInternal(packageName, permName, false,
1892                         Process.SYSTEM_UID, userId, delayingPermCallback);
1893             // In certain cases we should leave the state unchanged:
1894             // -- If permission review is enabled the permissions for a legacy apps
1895             // are represented as constantly granted runtime ones
1896             // -- If the permission was split from a non-runtime permission
1897             } else if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0
1898                     && !isPermissionSplitFromNonRuntime(permName, targetSdk)) {
1899                 // Otherwise, reset the permission.
1900                 revokeRuntimePermissionInternal(packageName, permName, false, Process.SYSTEM_UID,
1901                         userId, null, delayingPermCallback);
1902             }
1903         }
1904 
1905         // Execute delayed callbacks
1906         if (permissionRemoved[0]) {
1907             mDefaultPermissionCallback.onPermissionRemoved();
1908         }
1909 
1910         // Slight variation on the code in mPermissionCallback.onPermissionRevoked() as we cannot
1911         // kill uid while holding mPackages-lock
1912         if (!revokedPermissions.isEmpty()) {
1913             int numRevokedPermissions = revokedPermissions.size();
1914             for (int i = 0; i < numRevokedPermissions; i++) {
1915                 int revocationUID = IntPair.first(revokedPermissions.valueAt(i));
1916                 int revocationUserId = IntPair.second(revokedPermissions.valueAt(i));
1917 
1918                 mOnPermissionChangeListeners.onPermissionsChanged(revocationUID);
1919 
1920                 // Kill app later as we are holding mPackages
1921                 mHandler.post(() -> killUid(UserHandle.getAppId(revocationUID), revocationUserId,
1922                         KILL_APP_REASON_PERMISSIONS_REVOKED));
1923             }
1924         }
1925 
1926         mPackageManagerInt.writePermissionSettings(syncUpdatedUsers.toArray(), false);
1927         mPackageManagerInt.writePermissionSettings(asyncUpdatedUsers.toArray(), true);
1928     }
1929 
1930     /**
1931      * Determine if the given permission should be treated as split from a
1932      * non-runtime permission for an application targeting the given SDK level.
1933      */
isPermissionSplitFromNonRuntime(String permName, int targetSdk)1934     private boolean isPermissionSplitFromNonRuntime(String permName, int targetSdk) {
1935         final List<PermissionManager.SplitPermissionInfo> splitPerms = getSplitPermissionInfos();
1936         final int size = splitPerms.size();
1937         for (int i = 0; i < size; i++) {
1938             final PermissionManager.SplitPermissionInfo splitPerm = splitPerms.get(i);
1939             if (targetSdk < splitPerm.getTargetSdk()
1940                     && splitPerm.getNewPermissions().contains(permName)) {
1941                 synchronized (mLock) {
1942                     final Permission perm =
1943                             mRegistry.getPermission(splitPerm.getSplitPermission());
1944                     return perm != null && !perm.isRuntime();
1945                 }
1946             }
1947         }
1948         return false;
1949     }
1950 
1951     /**
1952      * This change makes it so that apps are told to show rationale for asking for background
1953      * location access every time they request.
1954      */
1955     @ChangeId
1956     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
1957     private static final long BACKGROUND_RATIONALE_CHANGE_ID = 147316723L;
1958 
1959     @Override
shouldShowRequestPermissionRationale(String packageName, String permName, @UserIdInt int userId)1960     public boolean shouldShowRequestPermissionRationale(String packageName, String permName,
1961             @UserIdInt int userId) {
1962         final int callingUid = Binder.getCallingUid();
1963         if (UserHandle.getCallingUserId() != userId) {
1964             mContext.enforceCallingPermission(
1965                     android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1966                     "canShowRequestPermissionRationale for user " + userId);
1967         }
1968 
1969         final int uid =
1970                 mPackageManagerInt.getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, userId);
1971         if (UserHandle.getAppId(callingUid) != UserHandle.getAppId(uid)) {
1972             return false;
1973         }
1974 
1975         if (checkPermission(packageName, permName, userId)
1976                 == PackageManager.PERMISSION_GRANTED) {
1977             return false;
1978         }
1979 
1980         final int flags;
1981 
1982         final long identity = Binder.clearCallingIdentity();
1983         try {
1984             flags = getPermissionFlagsInternal(packageName, permName, callingUid, userId);
1985         } finally {
1986             Binder.restoreCallingIdentity(identity);
1987         }
1988 
1989         final int fixedFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
1990                 | PackageManager.FLAG_PERMISSION_POLICY_FIXED
1991                 | PackageManager.FLAG_PERMISSION_USER_FIXED;
1992 
1993         if ((flags & fixedFlags) != 0) {
1994             return false;
1995         }
1996 
1997         synchronized (mLock) {
1998             final Permission permission = mRegistry.getPermission(permName);
1999             if (permission == null) {
2000                 return false;
2001             }
2002             if (permission.isHardRestricted()
2003                     && (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) == 0) {
2004                 return false;
2005             }
2006         }
2007 
2008         final long token = Binder.clearCallingIdentity();
2009         try {
2010             if (permName.equals(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
2011                     && mPlatformCompat.isChangeEnabledByPackageName(BACKGROUND_RATIONALE_CHANGE_ID,
2012                     packageName, userId)) {
2013                 return true;
2014             }
2015         } catch (RemoteException e) {
2016             Log.e(TAG, "Unable to check if compatibility change is enabled.", e);
2017         } finally {
2018             Binder.restoreCallingIdentity(token);
2019         }
2020 
2021         return (flags & PackageManager.FLAG_PERMISSION_USER_SET) != 0;
2022     }
2023 
2024     @Override
isPermissionRevokedByPolicy(String packageName, String permName, int userId)2025     public boolean isPermissionRevokedByPolicy(String packageName, String permName, int userId) {
2026         if (UserHandle.getCallingUserId() != userId) {
2027             mContext.enforceCallingPermission(
2028                     android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
2029                     "isPermissionRevokedByPolicy for user " + userId);
2030         }
2031 
2032         if (checkPermission(packageName, permName, userId) == PackageManager.PERMISSION_GRANTED) {
2033             return false;
2034         }
2035 
2036         final int callingUid = Binder.getCallingUid();
2037         if (mPackageManagerInt.filterAppAccess(packageName, callingUid, userId)) {
2038             return false;
2039         }
2040 
2041         final long identity = Binder.clearCallingIdentity();
2042         try {
2043             final int flags = getPermissionFlagsInternal(packageName, permName, callingUid, userId);
2044             return (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0;
2045         } finally {
2046             Binder.restoreCallingIdentity(identity);
2047         }
2048     }
2049 
2050     /**
2051      * Get the state of the runtime permissions as xml file.
2052      *
2053      * <p>Can not be called on main thread.
2054      *
2055      * @param userId The user ID the data should be extracted for
2056      *
2057      * @return The state as a xml file
2058      */
2059     @Nullable
backupRuntimePermissions(@serIdInt int userId)2060     private byte[] backupRuntimePermissions(@UserIdInt int userId) {
2061         CompletableFuture<byte[]> backup = new CompletableFuture<>();
2062         mPermissionControllerManager.getRuntimePermissionBackup(UserHandle.of(userId),
2063                 mContext.getMainExecutor(), backup::complete);
2064 
2065         try {
2066             return backup.get(BACKUP_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
2067         } catch (InterruptedException | ExecutionException  | TimeoutException e) {
2068             Slog.e(TAG, "Cannot create permission backup for user " + userId, e);
2069             return null;
2070         }
2071     }
2072 
2073     /**
2074      * Restore a permission state previously backed up via {@link #backupRuntimePermissions}.
2075      *
2076      * <p>If not all state can be restored, the un-appliable state will be delayed and can be
2077      * applied via {@link #restoreDelayedRuntimePermissions}.
2078      *
2079      * @param backup The state as an xml file
2080      * @param userId The user ID the data should be restored for
2081      */
restoreRuntimePermissions(@onNull byte[] backup, @UserIdInt int userId)2082     private void restoreRuntimePermissions(@NonNull byte[] backup, @UserIdInt int userId) {
2083         synchronized (mLock) {
2084             mHasNoDelayedPermBackup.delete(userId);
2085         }
2086         mPermissionControllerManager.stageAndApplyRuntimePermissionsBackup(backup,
2087                 UserHandle.of(userId));
2088     }
2089 
2090     /**
2091      * Try to apply permission backup that was previously not applied.
2092      *
2093      * <p>Can not be called on main thread.
2094      *
2095      * @param packageName The package that is newly installed
2096      * @param userId The user ID the package is installed for
2097      *
2098      * @see #restoreRuntimePermissions
2099      */
restoreDelayedRuntimePermissions(@onNull String packageName, @UserIdInt int userId)2100     private void restoreDelayedRuntimePermissions(@NonNull String packageName,
2101             @UserIdInt int userId) {
2102         synchronized (mLock) {
2103             if (mHasNoDelayedPermBackup.get(userId, false)) {
2104                 return;
2105             }
2106         }
2107         mPermissionControllerManager.applyStagedRuntimePermissionBackup(packageName,
2108                 UserHandle.of(userId), mContext.getMainExecutor(), (hasMoreBackup) -> {
2109                     if (hasMoreBackup) {
2110                         return;
2111                     }
2112                     synchronized (mLock) {
2113                         mHasNoDelayedPermBackup.put(userId, true);
2114                     }
2115                 });
2116     }
2117 
addOnRuntimePermissionStateChangedListener(@onNull OnRuntimePermissionStateChangedListener listener)2118     private void addOnRuntimePermissionStateChangedListener(@NonNull
2119             OnRuntimePermissionStateChangedListener listener) {
2120         synchronized (mLock) {
2121             mRuntimePermissionStateChangedListeners.add(listener);
2122         }
2123     }
2124 
removeOnRuntimePermissionStateChangedListener(@onNull OnRuntimePermissionStateChangedListener listener)2125     private void removeOnRuntimePermissionStateChangedListener(@NonNull
2126             OnRuntimePermissionStateChangedListener listener) {
2127         synchronized (mLock) {
2128             mRuntimePermissionStateChangedListeners.remove(listener);
2129         }
2130     }
2131 
notifyRuntimePermissionStateChanged(@onNull String packageName, @UserIdInt int userId)2132     private void notifyRuntimePermissionStateChanged(@NonNull String packageName,
2133             @UserIdInt int userId) {
2134         FgThread.getHandler().sendMessage(PooledLambda.obtainMessage
2135                 (PermissionManagerService::doNotifyRuntimePermissionStateChanged,
2136                         PermissionManagerService.this, packageName, userId));
2137     }
2138 
doNotifyRuntimePermissionStateChanged(@onNull String packageName, @UserIdInt int userId)2139     private void doNotifyRuntimePermissionStateChanged(@NonNull String packageName,
2140             @UserIdInt int userId) {
2141         final ArrayList<OnRuntimePermissionStateChangedListener> listeners;
2142         synchronized (mLock) {
2143             if (mRuntimePermissionStateChangedListeners.isEmpty()) {
2144                 return;
2145             }
2146             listeners = new ArrayList<>(mRuntimePermissionStateChangedListeners);
2147         }
2148         final int listenerCount = listeners.size();
2149         for (int i = 0; i < listenerCount; i++) {
2150             listeners.get(i).onRuntimePermissionStateChanged(packageName, userId);
2151         }
2152     }
2153 
startShellPermissionIdentityDelegationInternal(int uid, @NonNull String packageName, @Nullable List<String> permissionNames)2154     private void startShellPermissionIdentityDelegationInternal(int uid,
2155             @NonNull String packageName, @Nullable List<String> permissionNames) {
2156         synchronized (mLock) {
2157             final CheckPermissionDelegate oldDelegate = mCheckPermissionDelegate;
2158             if (oldDelegate != null && oldDelegate.getDelegatedUid() != uid) {
2159                 throw new SecurityException(
2160                         "Shell can delegate permissions only to one UID at a time");
2161             }
2162             final ShellDelegate delegate = new ShellDelegate(uid, packageName, permissionNames);
2163             setCheckPermissionDelegateLocked(delegate);
2164         }
2165     }
2166 
stopShellPermissionIdentityDelegationInternal()2167     private void stopShellPermissionIdentityDelegationInternal() {
2168         synchronized (mLock) {
2169             setCheckPermissionDelegateLocked(null);
2170         }
2171     }
2172 
2173     @Nullable
getDelegatedShellPermissionsInternal()2174     private List<String> getDelegatedShellPermissionsInternal() {
2175         synchronized (mLock) {
2176             if (mCheckPermissionDelegate == null) {
2177                 return Collections.EMPTY_LIST;
2178             }
2179             return mCheckPermissionDelegate.getDelegatedPermissionNames();
2180         }
2181     }
2182 
setCheckPermissionDelegateLocked(@ullable CheckPermissionDelegate delegate)2183     private void setCheckPermissionDelegateLocked(@Nullable CheckPermissionDelegate delegate) {
2184         if (delegate != null || mCheckPermissionDelegate != null) {
2185             PackageManager.invalidatePackageInfoCache();
2186         }
2187         mCheckPermissionDelegate = delegate;
2188     }
2189 
2190     /**
2191      * If the app is updated, and has scoped storage permissions, then it is possible that the
2192      * app updated in an attempt to get unscoped storage. If so, revoke all storage permissions.
2193      * @param newPackage The new package that was installed
2194      * @param oldPackage The old package that was updated
2195      */
revokeStoragePermissionsIfScopeExpandedInternal( @onNull AndroidPackage newPackage, @NonNull AndroidPackage oldPackage)2196     private void revokeStoragePermissionsIfScopeExpandedInternal(
2197             @NonNull AndroidPackage newPackage,
2198             @NonNull AndroidPackage oldPackage) {
2199         boolean downgradedSdk = oldPackage.getTargetSdkVersion() >= Build.VERSION_CODES.Q
2200                 && newPackage.getTargetSdkVersion() < Build.VERSION_CODES.Q;
2201         boolean upgradedSdk = oldPackage.getTargetSdkVersion() < Build.VERSION_CODES.Q
2202                 && newPackage.getTargetSdkVersion() >= Build.VERSION_CODES.Q;
2203         boolean newlyRequestsLegacy = !upgradedSdk && !oldPackage.isRequestLegacyExternalStorage()
2204                 && newPackage.isRequestLegacyExternalStorage();
2205 
2206         if (!newlyRequestsLegacy && !downgradedSdk) {
2207             return;
2208         }
2209 
2210         final int callingUid = Binder.getCallingUid();
2211         for (int userId: getAllUserIds()) {
2212             int numRequestedPermissions = newPackage.getRequestedPermissions().size();
2213             for (int i = 0; i < numRequestedPermissions; i++) {
2214                 PermissionInfo permInfo = getPermissionInfo(
2215                         newPackage.getRequestedPermissions().get(i),
2216                         newPackage.getPackageName(), 0);
2217                 if (permInfo == null || !STORAGE_PERMISSIONS.contains(permInfo.name)) {
2218                     continue;
2219                 }
2220 
2221                 EventLog.writeEvent(0x534e4554, "171430330", newPackage.getUid(),
2222                         "Revoking permission " + permInfo.name + " from package "
2223                                 + newPackage.getPackageName() + " as either the sdk downgraded "
2224                                 + downgradedSdk + " or newly requested legacy full storage "
2225                                 + newlyRequestsLegacy);
2226 
2227                 try {
2228                     revokeRuntimePermissionInternal(newPackage.getPackageName(), permInfo.name,
2229                             false, callingUid, userId, null, mDefaultPermissionCallback);
2230                 } catch (IllegalStateException | SecurityException e) {
2231                     Log.e(TAG, "unable to revoke " + permInfo.name + " for "
2232                             + newPackage.getPackageName() + " user " + userId, e);
2233                 }
2234             }
2235         }
2236 
2237     }
2238 
2239     /**
2240      * We might auto-grant permissions if any permission of the group is already granted. Hence if
2241      * the group of a granted permission changes we need to revoke it to avoid having permissions of
2242      * the new group auto-granted.
2243      *
2244      * @param newPackage The new package that was installed
2245      * @param oldPackage The old package that was updated
2246      */
2247     private void revokeRuntimePermissionsIfGroupChangedInternal(@NonNull AndroidPackage newPackage,
2248             @NonNull AndroidPackage oldPackage) {
2249         final int numOldPackagePermissions = ArrayUtils.size(oldPackage.getPermissions());
2250         final ArrayMap<String, String> oldPermissionNameToGroupName
2251                 = new ArrayMap<>(numOldPackagePermissions);
2252 
2253         for (int i = 0; i < numOldPackagePermissions; i++) {
2254             final ParsedPermission permission = oldPackage.getPermissions().get(i);
2255 
2256             if (permission.getParsedPermissionGroup() != null) {
2257                 oldPermissionNameToGroupName.put(permission.getName(),
2258                         permission.getParsedPermissionGroup().getName());
2259             }
2260         }
2261 
2262         final int callingUid = Binder.getCallingUid();
2263         final int numNewPackagePermissions = ArrayUtils.size(newPackage.getPermissions());
2264         for (int newPermissionNum = 0; newPermissionNum < numNewPackagePermissions;
2265                 newPermissionNum++) {
2266             final ParsedPermission newPermission =
2267                     newPackage.getPermissions().get(newPermissionNum);
2268             final int newProtection = newPermission.getProtection();
2269 
2270             if ((newProtection & PermissionInfo.PROTECTION_DANGEROUS) != 0) {
2271                 final String permissionName = newPermission.getName();
2272                 final String newPermissionGroupName =
2273                         newPermission.getParsedPermissionGroup() == null
2274                                 ? null : newPermission.getParsedPermissionGroup().getName();
2275                 final String oldPermissionGroupName = oldPermissionNameToGroupName.get(
2276                         permissionName);
2277 
2278                 if (newPermissionGroupName != null
2279                         && !newPermissionGroupName.equals(oldPermissionGroupName)) {
2280                     final int[] userIds = mUserManagerInt.getUserIds();
2281                     mPackageManagerInt.forEachPackage(pkg -> {
2282                         final String packageName = pkg.getPackageName();
2283                         for (final int userId : userIds) {
2284                             final int permissionState = checkPermission(packageName, permissionName,
2285                                     userId);
2286                             if (permissionState == PackageManager.PERMISSION_GRANTED) {
2287                                 EventLog.writeEvent(0x534e4554, "72710897",
2288                                         newPackage.getUid(),
2289                                         "Revoking permission " + permissionName +
2290                                         " from package " + packageName +
2291                                         " as the group changed from " + oldPermissionGroupName +
2292                                         " to " + newPermissionGroupName);
2293 
2294                                 try {
2295                                     revokeRuntimePermissionInternal(packageName, permissionName,
2296                                             false, callingUid, userId, null,
2297                                             mDefaultPermissionCallback);
2298                                 } catch (IllegalArgumentException e) {
2299                                     Slog.e(TAG, "Could not revoke " + permissionName + " from "
2300                                             + packageName, e);
2301                                 }
2302                             }
2303                         }
2304                     });
2305                 }
2306             }
2307         }
2308     }
2309 
2310     /**
2311      * If permissions are upgraded to runtime, or their owner changes to the system, then any
2312      * granted permissions must be revoked.
2313      *
2314      * @param permissionsToRevoke A list of permission names to revoke
2315      */
2316     private void revokeRuntimePermissionsIfPermissionDefinitionChangedInternal(
2317             @NonNull List<String> permissionsToRevoke) {
2318         final int[] userIds = mUserManagerInt.getUserIds();
2319         final int numPermissions = permissionsToRevoke.size();
2320         final int callingUid = Binder.getCallingUid();
2321 
2322         for (int permNum = 0; permNum < numPermissions; permNum++) {
2323             final String permName = permissionsToRevoke.get(permNum);
2324             synchronized (mLock) {
2325                 final Permission bp = mRegistry.getPermission(permName);
2326                 if (bp == null || !bp.isRuntime()) {
2327                     continue;
2328                 }
2329             }
2330             mPackageManagerInt.forEachPackage(pkg -> {
2331                 final String packageName = pkg.getPackageName();
2332                 final int appId = pkg.getUid();
2333                 if (appId < Process.FIRST_APPLICATION_UID) {
2334                     // do not revoke from system apps
2335                     return;
2336                 }
2337                 for (final int userId : userIds) {
2338                     final int permissionState = checkPermissionImpl(packageName, permName,
2339                             userId);
2340                     final int flags = getPermissionFlags(packageName, permName, userId);
2341                     final int flagMask = FLAG_PERMISSION_SYSTEM_FIXED
2342                             | FLAG_PERMISSION_POLICY_FIXED
2343                             | FLAG_PERMISSION_GRANTED_BY_DEFAULT
2344                             | FLAG_PERMISSION_GRANTED_BY_ROLE;
2345                     if (permissionState == PackageManager.PERMISSION_GRANTED
2346                             && (flags & flagMask) == 0) {
2347                         final int uid = UserHandle.getUid(userId, appId);
2348                         EventLog.writeEvent(0x534e4554, "154505240", uid,
2349                                 "Revoking permission " + permName + " from package "
2350                                         + packageName + " due to definition change");
2351                         EventLog.writeEvent(0x534e4554, "168319670", uid,
2352                                 "Revoking permission " + permName + " from package "
2353                                         + packageName + " due to definition change");
2354                         Slog.e(TAG, "Revoking permission " + permName + " from package "
2355                                 + packageName + " due to definition change");
2356                         try {
2357                             revokeRuntimePermissionInternal(packageName, permName,
2358                                     false, callingUid, userId, null, mDefaultPermissionCallback);
2359                         } catch (Exception e) {
2360                             Slog.e(TAG, "Could not revoke " + permName + " from "
2361                                     + packageName, e);
2362                         }
2363                     }
2364                 }
2365             });
2366         }
2367     }
2368 
2369     private List<String> addAllPermissionsInternal(@NonNull AndroidPackage pkg) {
2370         final int N = ArrayUtils.size(pkg.getPermissions());
2371         ArrayList<String> definitionChangedPermissions = new ArrayList<>();
2372         for (int i=0; i<N; i++) {
2373             ParsedPermission p = pkg.getPermissions().get(i);
2374 
2375             // Assume by default that we did not install this permission into the system.
2376             p.setFlags(p.getFlags() & ~PermissionInfo.FLAG_INSTALLED);
2377 
2378             final PermissionInfo permissionInfo;
2379             final Permission oldPermission;
2380             synchronized (mLock) {
2381                 // Now that permission groups have a special meaning, we ignore permission
2382                 // groups for legacy apps to prevent unexpected behavior. In particular,
2383                 // permissions for one app being granted to someone just because they happen
2384                 // to be in a group defined by another app (before this had no implications).
2385                 if (pkg.getTargetSdkVersion() > Build.VERSION_CODES.LOLLIPOP_MR1) {
2386                     p.setParsedPermissionGroup(mRegistry.getPermissionGroup(p.getGroup()));
2387                     // Warn for a permission in an unknown group.
2388                     if (DEBUG_PERMISSIONS
2389                             && p.getGroup() != null && p.getParsedPermissionGroup() == null) {
2390                         Slog.i(TAG, "Permission " + p.getName() + " from package "
2391                                 + p.getPackageName() + " in an unknown group " + p.getGroup());
2392                     }
2393                 }
2394 
2395                 permissionInfo = PackageInfoUtils.generatePermissionInfo(p,
2396                         PackageManager.GET_META_DATA);
2397                 oldPermission = p.isTree() ? mRegistry.getPermissionTree(p.getName())
2398                         : mRegistry.getPermission(p.getName());
2399             }
2400             // TODO(zhanghai): Maybe we should store whether a permission is owned by system inside
2401             //  itself.
2402             final boolean isOverridingSystemPermission = Permission.isOverridingSystemPermission(
2403                     oldPermission, permissionInfo, mPackageManagerInt);
2404             synchronized (mLock) {
2405                 final Permission permission = Permission.createOrUpdate(oldPermission,
2406                         permissionInfo, pkg, mRegistry.getPermissionTrees(),
2407                         isOverridingSystemPermission);
2408                 if (p.isTree()) {
2409                     mRegistry.addPermissionTree(permission);
2410                 } else {
2411                     mRegistry.addPermission(permission);
2412                 }
2413                 if (permission.isInstalled()) {
2414                     p.setFlags(p.getFlags() | PermissionInfo.FLAG_INSTALLED);
2415                 }
2416                 if (permission.isDefinitionChanged()) {
2417                     definitionChangedPermissions.add(p.getName());
2418                     permission.setDefinitionChanged(false);
2419                 }
2420             }
2421         }
2422         return definitionChangedPermissions;
2423     }
2424 
2425     private void addAllPermissionGroupsInternal(@NonNull AndroidPackage pkg) {
2426         synchronized (mLock) {
2427             final int N = ArrayUtils.size(pkg.getPermissionGroups());
2428             StringBuilder r = null;
2429             for (int i = 0; i < N; i++) {
2430                 final ParsedPermissionGroup pg = pkg.getPermissionGroups().get(i);
2431                 final ParsedPermissionGroup cur = mRegistry.getPermissionGroup(pg.getName());
2432                 final String curPackageName = (cur == null) ? null : cur.getPackageName();
2433                 final boolean isPackageUpdate = pg.getPackageName().equals(curPackageName);
2434                 if (cur == null || isPackageUpdate) {
2435                     mRegistry.addPermissionGroup(pg);
2436                     if (DEBUG_PACKAGE_SCANNING) {
2437                         if (r == null) {
2438                             r = new StringBuilder(256);
2439                         } else {
2440                             r.append(' ');
2441                         }
2442                         if (isPackageUpdate) {
2443                             r.append("UPD:");
2444                         }
2445                         r.append(pg.getName());
2446                     }
2447                 } else {
2448                     Slog.w(TAG, "Permission group " + pg.getName() + " from package "
2449                             + pg.getPackageName() + " ignored: original from "
2450                             + cur.getPackageName());
2451                     if (DEBUG_PACKAGE_SCANNING) {
2452                         if (r == null) {
2453                             r = new StringBuilder(256);
2454                         } else {
2455                             r.append(' ');
2456                         }
2457                         r.append("DUP:");
2458                         r.append(pg.getName());
2459                     }
2460                 }
2461             }
2462             if (r != null && DEBUG_PACKAGE_SCANNING) {
2463                 Log.d(TAG, "  Permission Groups: " + r);
2464             }
2465         }
2466     }
2467 
2468     private void removeAllPermissionsInternal(@NonNull AndroidPackage pkg) {
2469         synchronized (mLock) {
2470             int N = ArrayUtils.size(pkg.getPermissions());
2471             StringBuilder r = null;
2472             for (int i=0; i<N; i++) {
2473                 ParsedPermission p = pkg.getPermissions().get(i);
2474                 Permission bp = mRegistry.getPermission(p.getName());
2475                 if (bp == null) {
2476                     bp = mRegistry.getPermissionTree(p.getName());
2477                 }
2478                 if (bp != null && bp.isPermission(p)) {
2479                     bp.setPermissionInfo(null);
2480                     if (DEBUG_REMOVE) {
2481                         if (r == null) {
2482                             r = new StringBuilder(256);
2483                         } else {
2484                             r.append(' ');
2485                         }
2486                         r.append(p.getName());
2487                     }
2488                 }
2489                 if (p.isAppOp()) {
2490                     // TODO(zhanghai): Should we just remove the entry for this permission directly?
2491                     mRegistry.removeAppOpPermissionPackage(p.getName(), pkg.getPackageName());
2492                 }
2493             }
2494             if (r != null) {
2495                 if (DEBUG_REMOVE) Log.d(TAG, "  Permissions: " + r);
2496             }
2497 
2498             N = pkg.getRequestedPermissions().size();
2499             r = null;
2500             for (int i=0; i<N; i++) {
2501                 final String permissionName = pkg.getRequestedPermissions().get(i);
2502                 final Permission permission = mRegistry.getPermission(permissionName);
2503                 if (permission != null && permission.isAppOp()) {
2504                     mRegistry.removeAppOpPermissionPackage(permissionName,
2505                             pkg.getPackageName());
2506                 }
2507             }
2508             if (r != null) {
2509                 if (DEBUG_REMOVE) Log.d(TAG, "  Permissions: " + r);
2510             }
2511         }
2512     }
2513 
2514     private void onUserRemoved(@UserIdInt int userId) {
2515         synchronized (mLock) {
2516             mState.removeUserState(userId);
2517         }
2518     }
2519 
2520     @NonNull
2521     private Set<String> getGrantedPermissionsInternal(@NonNull String packageName,
2522             @UserIdInt int userId) {
2523         final PackageSetting ps = mPackageManagerInt.getPackageSetting(packageName);
2524         if (ps == null) {
2525             return Collections.emptySet();
2526         }
2527 
2528         synchronized (mLock) {
2529             final UidPermissionState uidState = getUidStateLocked(ps, userId);
2530             if (uidState == null) {
2531                 Slog.e(TAG, "Missing permissions state for " + packageName + " and user " + userId);
2532                 return Collections.emptySet();
2533             }
2534             if (!ps.getInstantApp(userId)) {
2535                 return uidState.getGrantedPermissions();
2536             } else {
2537                 // Install permission state is shared among all users, but instant app state is
2538                 // per-user, so we can only filter it here unless we make install permission state
2539                 // per-user as well.
2540                 final Set<String> instantPermissions =
2541                         new ArraySet<>(uidState.getGrantedPermissions());
2542                 instantPermissions.removeIf(permissionName -> {
2543                     Permission permission = mRegistry.getPermission(permissionName);
2544                     if (permission == null) {
2545                         return true;
2546                     }
2547                     if (!permission.isInstant()) {
2548                         EventLog.writeEvent(0x534e4554, "140256621", UserHandle.getUid(userId,
2549                                 ps.getAppId()), permissionName);
2550                         return true;
2551                     }
2552                     return false;
2553                 });
2554                 return instantPermissions;
2555             }
2556         }
2557     }
2558 
2559     @NonNull
2560     private int[] getPermissionGidsInternal(@NonNull String permissionName, @UserIdInt int userId) {
2561         synchronized (mLock) {
2562             Permission permission = mRegistry.getPermission(permissionName);
2563             if (permission == null) {
2564                 return EmptyArray.INT;
2565             }
2566             return permission.computeGids(userId);
2567         }
2568     }
2569 
2570     /**
2571      * Restore the permission state for a package.
2572      *
2573      * <ul>
2574      *     <li>During boot the state gets restored from the disk</li>
2575      *     <li>During app update the state gets restored from the last version of the app</li>
2576      * </ul>
2577      *
2578      * @param pkg the package the permissions belong to
2579      * @param replace if the package is getting replaced (this might change the requested
2580      *                permissions of this package)
2581      * @param packageOfInterest If this is the name of {@code pkg} add extra logging
2582      * @param callback Result call back
2583      * @param filterUserId If not {@link UserHandle.USER_ALL}, only restore the permission state for
2584      *                     this particular user
2585      */
2586     private void restorePermissionState(@NonNull AndroidPackage pkg, boolean replace,
2587             @Nullable String packageOfInterest, @Nullable PermissionCallback callback,
2588             @UserIdInt int filterUserId) {
2589         // IMPORTANT: There are two types of permissions: install and runtime.
2590         // Install time permissions are granted when the app is installed to
2591         // all device users and users added in the future. Runtime permissions
2592         // are granted at runtime explicitly to specific users. Normal and signature
2593         // protected permissions are install time permissions. Dangerous permissions
2594         // are install permissions if the app's target SDK is Lollipop MR1 or older,
2595         // otherwise they are runtime permissions. This function does not manage
2596         // runtime permissions except for the case an app targeting Lollipop MR1
2597         // being upgraded to target a newer SDK, in which case dangerous permissions
2598         // are transformed from install time to runtime ones.
2599 
2600         final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
2601                 pkg.getPackageName());
2602         if (ps == null) {
2603             return;
2604         }
2605 
2606         final int[] userIds = filterUserId == UserHandle.USER_ALL ? getAllUserIds()
2607                 : new int[] { filterUserId };
2608 
2609         boolean runtimePermissionsRevoked = false;
2610         int[] updatedUserIds = EMPTY_INT_ARRAY;
2611 
2612         ArraySet<String> isPrivilegedPermissionAllowlisted = null;
2613         ArraySet<String> shouldGrantSignaturePermission = null;
2614         ArraySet<String> shouldGrantInternalPermission = null;
2615         ArraySet<String> shouldGrantPrivilegedPermissionIfWasGranted = new ArraySet<>();
2616         final List<String> requestedPermissions = pkg.getRequestedPermissions();
2617         final int requestedPermissionsSize = requestedPermissions.size();
2618         for (int i = 0; i < requestedPermissionsSize; i++) {
2619             final String permissionName = pkg.getRequestedPermissions().get(i);
2620 
2621             final Permission permission;
2622             synchronized (mLock) {
2623                 permission = mRegistry.getPermission(permissionName);
2624             }
2625             if (permission == null) {
2626                 continue;
2627             }
2628             if (permission.isPrivileged()
2629                     && checkPrivilegedPermissionAllowlist(pkg, ps, permission)) {
2630                 if (isPrivilegedPermissionAllowlisted == null) {
2631                     isPrivilegedPermissionAllowlisted = new ArraySet<>();
2632                 }
2633                 isPrivilegedPermissionAllowlisted.add(permissionName);
2634             }
2635             if (permission.isSignature() && (shouldGrantPermissionBySignature(pkg, permission)
2636                     || shouldGrantPermissionByProtectionFlags(pkg, ps, permission,
2637                             shouldGrantPrivilegedPermissionIfWasGranted))) {
2638                 if (shouldGrantSignaturePermission == null) {
2639                     shouldGrantSignaturePermission = new ArraySet<>();
2640                 }
2641                 shouldGrantSignaturePermission.add(permissionName);
2642             }
2643             if (permission.isInternal()
2644                     && shouldGrantPermissionByProtectionFlags(pkg, ps, permission,
2645                             shouldGrantPrivilegedPermissionIfWasGranted)) {
2646                 if (shouldGrantInternalPermission == null) {
2647                     shouldGrantInternalPermission = new ArraySet<>();
2648                 }
2649                 shouldGrantInternalPermission.add(permissionName);
2650             }
2651         }
2652 
2653         final SparseBooleanArray isPermissionPolicyInitialized = new SparseBooleanArray();
2654         if (mPermissionPolicyInternal != null) {
2655             for (final int userId : userIds) {
2656                 if (mPermissionPolicyInternal.isInitialized(userId)) {
2657                     isPermissionPolicyInitialized.put(userId, true);
2658                 }
2659             }
2660         }
2661 
2662         synchronized (mLock) {
2663             for (final int userId : userIds) {
2664                 final UserPermissionState userState = mState.getOrCreateUserState(userId);
2665                 final UidPermissionState uidState = userState.getOrCreateUidState(ps.getAppId());
2666 
2667                 if (uidState.isMissing()) {
2668                     Collection<String> uidRequestedPermissions;
2669                     int targetSdkVersion;
2670                     if (!ps.isSharedUser()) {
2671                         uidRequestedPermissions = pkg.getRequestedPermissions();
2672                         targetSdkVersion = pkg.getTargetSdkVersion();
2673                     } else {
2674                         uidRequestedPermissions = new ArraySet<>();
2675                         targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
2676                         List<AndroidPackage> packages = ps.getSharedUser().getPackages();
2677                         int packagesSize = packages.size();
2678                         for (int i = 0; i < packagesSize; i++) {
2679                             AndroidPackage sharedUserPackage = packages.get(i);
2680                             uidRequestedPermissions.addAll(
2681                                     sharedUserPackage.getRequestedPermissions());
2682                             targetSdkVersion = Math.min(targetSdkVersion,
2683                                     sharedUserPackage.getTargetSdkVersion());
2684                         }
2685                     }
2686 
2687                     for (String permissionName : uidRequestedPermissions) {
2688                         Permission permission = mRegistry.getPermission(permissionName);
2689                         if (permission == null) {
2690                             continue;
2691                         }
2692                         if (Objects.equals(permission.getPackageName(), PLATFORM_PACKAGE_NAME)
2693                                 && permission.isRuntime() && !permission.isRemoved()) {
2694                             if (permission.isHardOrSoftRestricted()
2695                                     || permission.isImmutablyRestricted()) {
2696                                 uidState.updatePermissionFlags(permission,
2697                                         FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT,
2698                                         FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT);
2699                             }
2700                             if (targetSdkVersion < Build.VERSION_CODES.M) {
2701                                 uidState.updatePermissionFlags(permission,
2702                                         PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
2703                                                 | PackageManager.FLAG_PERMISSION_REVOKED_COMPAT,
2704                                         PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
2705                                                 | PackageManager.FLAG_PERMISSION_REVOKED_COMPAT);
2706                                 uidState.grantPermission(permission);
2707                             }
2708                         }
2709                     }
2710 
2711                     uidState.setMissing(false);
2712                     updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
2713                 }
2714 
2715                 UidPermissionState origState = uidState;
2716 
2717                 boolean changedInstallPermission = false;
2718 
2719                 if (replace) {
2720                     userState.setInstallPermissionsFixed(ps.name, false);
2721                     if (!ps.isSharedUser()) {
2722                         origState = new UidPermissionState(uidState);
2723                         uidState.reset();
2724                     } else {
2725                         // We need to know only about runtime permission changes since the
2726                         // calling code always writes the install permissions state but
2727                         // the runtime ones are written only if changed. The only cases of
2728                         // changed runtime permissions here are promotion of an install to
2729                         // runtime and revocation of a runtime from a shared user.
2730                         if (revokeUnusedSharedUserPermissionsLocked(
2731                                 ps.getSharedUser().getPackages(), uidState)) {
2732                             updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
2733                             runtimePermissionsRevoked = true;
2734                         }
2735                     }
2736                 }
2737 
2738                 ArraySet<String> newImplicitPermissions = new ArraySet<>();
2739                 final String friendlyName = pkg.getPackageName() + "(" + pkg.getUid() + ")";
2740 
2741                 for (int i = 0; i < requestedPermissionsSize; i++) {
2742                     final String permName = requestedPermissions.get(i);
2743 
2744                     final Permission bp = mRegistry.getPermission(permName);
2745                     final boolean appSupportsRuntimePermissions =
2746                             pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M;
2747                     String legacyActivityRecognitionPermission = null;
2748 
2749                     if (DEBUG_INSTALL && bp != null) {
2750                         Log.i(TAG, "Package " + friendlyName
2751                                 + " checking " + permName + ": " + bp);
2752                     }
2753 
2754                     // TODO(zhanghai): I don't think we need to check source package setting if
2755                     //  permission is present, because otherwise the permission should have been
2756                     //  removed.
2757                     if (bp == null /*|| getSourcePackageSetting(bp) == null*/) {
2758                         if (packageOfInterest == null || packageOfInterest.equals(
2759                                 pkg.getPackageName())) {
2760                             if (DEBUG_PERMISSIONS) {
2761                                 Slog.i(TAG, "Unknown permission " + permName
2762                                         + " in package " + friendlyName);
2763                             }
2764                         }
2765                         continue;
2766                     }
2767 
2768                     // Cache newImplicitPermissions before modifing permissionsState as for the
2769                     // shared uids the original and new state are the same object
2770                     if (!origState.hasPermissionState(permName)
2771                             && (pkg.getImplicitPermissions().contains(permName)
2772                             || (permName.equals(Manifest.permission.ACTIVITY_RECOGNITION)))) {
2773                         if (pkg.getImplicitPermissions().contains(permName)) {
2774                             // If permName is an implicit permission, try to auto-grant
2775                             newImplicitPermissions.add(permName);
2776 
2777                             if (DEBUG_PERMISSIONS) {
2778                                 Slog.i(TAG, permName + " is newly added for " + friendlyName);
2779                             }
2780                         } else {
2781                             // Special case for Activity Recognition permission. Even if AR
2782                             // permission is not an implicit permission we want to add it to the
2783                             // list (try to auto-grant it) if the app was installed on a device
2784                             // before AR permission was split, regardless of if the app now requests
2785                             // the new AR permission or has updated its target SDK and AR is no
2786                             // longer implicit to it. This is a compatibility workaround for apps
2787                             // when AR permission was split in Q.
2788                             // TODO(zhanghai): This calls into SystemConfig, which generally
2789                             //  shouldn't  cause deadlock, but maybe we should keep a cache of the
2790                             //  split permission  list and just eliminate the possibility.
2791                             final List<PermissionManager.SplitPermissionInfo> permissionList =
2792                                     getSplitPermissionInfos();
2793                             int numSplitPerms = permissionList.size();
2794                             for (int splitPermNum = 0; splitPermNum < numSplitPerms;
2795                                     splitPermNum++) {
2796                                 PermissionManager.SplitPermissionInfo sp = permissionList.get(
2797                                         splitPermNum);
2798                                 String splitPermName = sp.getSplitPermission();
2799                                 if (sp.getNewPermissions().contains(permName)
2800                                         && origState.isPermissionGranted(splitPermName)) {
2801                                     legacyActivityRecognitionPermission = splitPermName;
2802                                     newImplicitPermissions.add(permName);
2803 
2804                                     if (DEBUG_PERMISSIONS) {
2805                                         Slog.i(TAG, permName + " is newly added for "
2806                                                 + friendlyName);
2807                                     }
2808                                     break;
2809                                 }
2810                             }
2811                         }
2812                     }
2813 
2814                     // TODO(b/140256621): The package instant app method has been removed
2815                     //  as part of work in b/135203078, so this has been commented out in the
2816                     //  meantime
2817                     // Limit ephemeral apps to ephemeral allowed permissions.
2818         //            if (/*pkg.isInstantApp()*/ false && !bp.isInstant()) {
2819         //                if (DEBUG_PERMISSIONS) {
2820         //                    Log.i(TAG, "Denying non-ephemeral permission " + bp.getName()
2821         //                            + " for package " + pkg.getPackageName());
2822         //                }
2823         //                continue;
2824         //            }
2825 
2826                     if (bp.isRuntimeOnly() && !appSupportsRuntimePermissions) {
2827                         if (DEBUG_PERMISSIONS) {
2828                             Log.i(TAG, "Denying runtime-only permission " + bp.getName()
2829                                     + " for package " + friendlyName);
2830                         }
2831                         continue;
2832                     }
2833 
2834                     final String perm = bp.getName();
2835 
2836                     // Keep track of app op permissions.
2837                     if (bp.isAppOp()) {
2838                         mRegistry.addAppOpPermissionPackage(perm, pkg.getPackageName());
2839                     }
2840 
2841                     boolean shouldGrantNormalPermission = true;
2842                     if (bp.isNormal() && !origState.isPermissionGranted(perm)) {
2843                         // If this is an existing, non-system package, then
2844                         // we can't add any new permissions to it. Runtime
2845                         // permissions can be added any time - they are dynamic.
2846                         if (!ps.isSystem() && userState.areInstallPermissionsFixed(ps.name)) {
2847                             // Except...  if this is a permission that was added
2848                             // to the platform (note: need to only do this when
2849                             // updating the platform).
2850                             if (!isNewPlatformPermissionForPackage(perm, pkg)) {
2851                                 shouldGrantNormalPermission = false;
2852                             }
2853                         }
2854                     }
2855 
2856                     if (DEBUG_PERMISSIONS) {
2857                         Slog.i(TAG, "Considering granting permission " + perm + " to package "
2858                                 + pkg.getPackageName());
2859                     }
2860 
2861                     if ((bp.isNormal() && shouldGrantNormalPermission)
2862                             || (bp.isSignature()
2863                                     && (!bp.isPrivileged() || CollectionUtils.contains(
2864                                             isPrivilegedPermissionAllowlisted, permName))
2865                                     && (CollectionUtils.contains(shouldGrantSignaturePermission,
2866                                             permName)
2867                                             || (((bp.isPrivileged() && CollectionUtils.contains(
2868                                                     shouldGrantPrivilegedPermissionIfWasGranted,
2869                                                     permName)) || bp.isDevelopment() || bp.isRole())
2870                                                     && origState.isPermissionGranted(permName))))
2871                             || (bp.isInternal()
2872                                     && (!bp.isPrivileged() || CollectionUtils.contains(
2873                                             isPrivilegedPermissionAllowlisted, permName))
2874                                     && (CollectionUtils.contains(shouldGrantInternalPermission,
2875                                             permName)
2876                                             || (((bp.isPrivileged() && CollectionUtils.contains(
2877                                                     shouldGrantPrivilegedPermissionIfWasGranted,
2878                                                     permName)) || bp.isDevelopment() || bp.isRole())
2879                                                     && origState.isPermissionGranted(permName))))) {
2880                         // Grant an install permission.
2881                         if (uidState.grantPermission(bp)) {
2882                             changedInstallPermission = true;
2883                         }
2884                     } else if (bp.isRuntime()) {
2885                         boolean hardRestricted = bp.isHardRestricted();
2886                         boolean softRestricted = bp.isSoftRestricted();
2887 
2888                         // If permission policy is not ready we don't deal with restricted
2889                         // permissions as the policy may allowlist some permissions. Once
2890                         // the policy is initialized we would re-evaluate permissions.
2891                         final boolean permissionPolicyInitialized =
2892                                 isPermissionPolicyInitialized.get(userId);
2893 
2894                         PermissionState origPermState = origState.getPermissionState(perm);
2895                         int flags = origPermState != null ? origPermState.getFlags() : 0;
2896 
2897                         boolean wasChanged = false;
2898 
2899                         boolean restrictionExempt =
2900                                 (origState.getPermissionFlags(bp.getName())
2901                                         & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;
2902                         boolean restrictionApplied = (origState.getPermissionFlags(
2903                                 bp.getName()) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
2904 
2905                         if (appSupportsRuntimePermissions) {
2906                             // If hard restricted we don't allow holding it
2907                             if (permissionPolicyInitialized && hardRestricted) {
2908                                 if (!restrictionExempt) {
2909                                     if (origPermState != null && origPermState.isGranted()
2910                                             && uidState.revokePermission(bp)) {
2911                                         wasChanged = true;
2912                                     }
2913                                     if (!restrictionApplied) {
2914                                         flags |= FLAG_PERMISSION_APPLY_RESTRICTION;
2915                                         wasChanged = true;
2916                                     }
2917                                 }
2918                             // If soft restricted we allow holding in a restricted form
2919                             } else if (permissionPolicyInitialized && softRestricted) {
2920                                 // Regardless if granted set the restriction flag as it
2921                                 // may affect app treatment based on this permission.
2922                                 if (!restrictionExempt && !restrictionApplied) {
2923                                     flags |= FLAG_PERMISSION_APPLY_RESTRICTION;
2924                                     wasChanged = true;
2925                                 }
2926                             }
2927 
2928                             // Remove review flag as it is not necessary anymore
2929                             if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
2930                                 flags &= ~FLAG_PERMISSION_REVIEW_REQUIRED;
2931                                 wasChanged = true;
2932                             }
2933 
2934                             if ((flags & FLAG_PERMISSION_REVOKED_COMPAT) != 0
2935                                     && !isPermissionSplitFromNonRuntime(permName,
2936                                     pkg.getTargetSdkVersion())) {
2937                                 flags &= ~FLAG_PERMISSION_REVOKED_COMPAT;
2938                                 wasChanged = true;
2939                             // Hard restricted permissions cannot be held.
2940                             } else if (!permissionPolicyInitialized
2941                                     || (!hardRestricted || restrictionExempt)) {
2942                                 if ((origPermState != null && origPermState.isGranted())
2943                                         || legacyActivityRecognitionPermission != null) {
2944                                     if (!uidState.grantPermission(bp)) {
2945                                         wasChanged = true;
2946                                     }
2947                                 }
2948                             }
2949                         } else {
2950                             if (origPermState == null) {
2951                                 // New permission
2952                                 if (PLATFORM_PACKAGE_NAME.equals(
2953                                         bp.getPackageName())) {
2954                                     if (!bp.isRemoved()) {
2955                                         flags |= FLAG_PERMISSION_REVIEW_REQUIRED
2956                                                 | FLAG_PERMISSION_REVOKED_COMPAT;
2957                                         wasChanged = true;
2958                                     }
2959                                 }
2960                             }
2961 
2962                             if (!uidState.isPermissionGranted(bp.getName())
2963                                     && uidState.grantPermission(bp)) {
2964                                 wasChanged = true;
2965                             }
2966 
2967                             // If legacy app always grant the permission but if restricted
2968                             // and not exempt take a note a restriction should be applied.
2969                             if (permissionPolicyInitialized
2970                                     && (hardRestricted || softRestricted)
2971                                             && !restrictionExempt && !restrictionApplied) {
2972                                 flags |= FLAG_PERMISSION_APPLY_RESTRICTION;
2973                                 wasChanged = true;
2974                             }
2975                         }
2976 
2977                         // If unrestricted or restriction exempt, don't apply restriction.
2978                         if (permissionPolicyInitialized) {
2979                             if (!(hardRestricted || softRestricted) || restrictionExempt) {
2980                                 if (restrictionApplied) {
2981                                     flags &= ~FLAG_PERMISSION_APPLY_RESTRICTION;
2982                                     // Dropping restriction on a legacy app implies a review
2983                                     if (!appSupportsRuntimePermissions) {
2984                                         flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
2985                                     }
2986                                     wasChanged = true;
2987                                 }
2988                             }
2989                         }
2990 
2991                         if (wasChanged) {
2992                             updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
2993                         }
2994 
2995                         uidState.updatePermissionFlags(bp, MASK_PERMISSION_FLAGS_ALL,
2996                                 flags);
2997                     } else {
2998                         if (DEBUG_PERMISSIONS) {
2999                             boolean wasGranted = uidState.isPermissionGranted(bp.getName());
3000                             if (wasGranted || bp.isAppOp()) {
3001                                 Slog.i(TAG, (wasGranted ? "Un-granting" : "Not granting")
3002                                         + " permission " + perm
3003                                         + " from package " + friendlyName
3004                                         + " (protectionLevel=" + bp.getProtectionLevel()
3005                                         + " flags=0x"
3006                                         + Integer.toHexString(PackageInfoUtils.appInfoFlags(pkg,
3007                                                 ps))
3008                                         + ")");
3009                             }
3010                         }
3011                         if (uidState.removePermissionState(bp.getName())) {
3012                             changedInstallPermission = true;
3013                         }
3014                     }
3015                 }
3016 
3017                 if ((changedInstallPermission || replace)
3018                         && !userState.areInstallPermissionsFixed(ps.name)
3019                         && !ps.isSystem() || ps.getPkgState().isUpdatedSystemApp()) {
3020                     // This is the first that we have heard about this package, so the
3021                     // permissions we have now selected are fixed until explicitly
3022                     // changed.
3023                     userState.setInstallPermissionsFixed(ps.name, true);
3024                 }
3025 
3026                 updatedUserIds = revokePermissionsNoLongerImplicitLocked(uidState, pkg,
3027                         userId, updatedUserIds);
3028                 updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origState,
3029                         uidState, pkg, newImplicitPermissions, userId, updatedUserIds);
3030             }
3031         }
3032 
3033         updatedUserIds = checkIfLegacyStorageOpsNeedToBeUpdated(pkg, replace, userIds,
3034                 updatedUserIds);
3035 
3036         // TODO: Kill UIDs whose GIDs or runtime permissions changed. This might be more important
3037         //  for shared users.
3038         // Persist the runtime permissions state for users with changes. If permissions
3039         // were revoked because no app in the shared user declares them we have to
3040         // write synchronously to avoid losing runtime permissions state.
3041         if (callback != null) {
3042             callback.onPermissionUpdated(updatedUserIds, runtimePermissionsRevoked);
3043         }
3044 
3045         for (int userId : updatedUserIds) {
3046             notifyRuntimePermissionStateChanged(pkg.getPackageName(), userId);
3047         }
3048     }
3049 
3050     /**
3051      * Returns all relevant user ids.  This list include the current set of created user ids as well
3052      * as pre-created user ids.
3053      * @return user ids for created users and pre-created users
3054      */
3055     private int[] getAllUserIds() {
3056         return UserManagerService.getInstance().getUserIdsIncludingPreCreated();
3057     }
3058 
3059     /**
3060      * Revoke permissions that are not implicit anymore and that have
3061      * {@link PackageManager#FLAG_PERMISSION_REVOKE_WHEN_REQUESTED} set.
3062      *
3063      * @param ps The state of the permissions of the package
3064      * @param pkg The package that is currently looked at
3065      * @param userIds All user IDs in the system, must be passed in because this method is locked
3066      * @param updatedUserIds a list of user ids that needs to be amended if the permission state
3067      *                       for a user is changed.
3068      *
3069      * @return The updated value of the {@code updatedUserIds} parameter
3070      */
3071     @GuardedBy("mLock")
3072     private @NonNull int[] revokePermissionsNoLongerImplicitLocked(@NonNull UidPermissionState ps,
3073             @NonNull AndroidPackage pkg, int userId, @NonNull int[] updatedUserIds) {
3074         String pkgName = pkg.getPackageName();
3075         boolean supportsRuntimePermissions = pkg.getTargetSdkVersion()
3076                 >= Build.VERSION_CODES.M;
3077 
3078         for (String permission : ps.getGrantedPermissions()) {
3079             if (pkg.getRequestedPermissions().contains(permission)
3080                     && !pkg.getImplicitPermissions().contains(permission)) {
3081                 Permission bp = mRegistry.getPermission(permission);
3082                 if (bp != null && bp.isRuntime()) {
3083                     int flags = ps.getPermissionFlags(permission);
3084                     if ((flags & FLAG_PERMISSION_REVOKE_WHEN_REQUESTED) != 0) {
3085                         int flagsToRemove = FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
3086 
3087                         // We're willing to preserve an implicit "Nearby devices"
3088                         // permission grant if this app was already able to interact
3089                         // with nearby devices via background location access
3090                         boolean preserveGrant = false;
3091                         if (ArrayUtils.contains(NEARBY_DEVICES_PERMISSIONS, permission)
3092                                 && ps.isPermissionGranted(
3093                                         android.Manifest.permission.ACCESS_BACKGROUND_LOCATION)
3094                                 && (ps.getPermissionFlags(
3095                                         android.Manifest.permission.ACCESS_BACKGROUND_LOCATION)
3096                                         & (FLAG_PERMISSION_REVOKE_WHEN_REQUESTED
3097                                                 | FLAG_PERMISSION_REVOKED_COMPAT)) == 0) {
3098                             preserveGrant = true;
3099                         }
3100 
3101                         if ((flags & BLOCKING_PERMISSION_FLAGS) == 0
3102                                 && supportsRuntimePermissions
3103                                 && !preserveGrant) {
3104                             if (ps.revokePermission(bp)) {
3105                                 if (DEBUG_PERMISSIONS) {
3106                                     Slog.i(TAG, "Revoking runtime permission "
3107                                             + permission + " for " + pkgName
3108                                             + " as it is now requested");
3109                                 }
3110                             }
3111 
3112                             flagsToRemove |= USER_PERMISSION_FLAGS;
3113                         }
3114 
3115                         ps.updatePermissionFlags(bp, flagsToRemove, 0);
3116                         updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
3117                     }
3118                 }
3119             }
3120         }
3121 
3122         return updatedUserIds;
3123     }
3124 
3125     /**
3126      * {@code newPerm} is newly added; Inherit the state from {@code sourcePerms}.
3127      *
3128      * <p>A single new permission can be split off from several source permissions. In this case
3129      * the most leniant state is inherited.
3130      *
3131      * <p>Warning: This does not handle foreground / background permissions
3132      *
3133      * @param sourcePerms The permissions to inherit from
3134      * @param newPerm The permission to inherit to
3135      * @param ps The permission state of the package
3136      * @param pkg The package requesting the permissions
3137      */
3138     @GuardedBy("mLock")
3139     private void inheritPermissionStateToNewImplicitPermissionLocked(
3140             @NonNull ArraySet<String> sourcePerms, @NonNull String newPerm,
3141             @NonNull UidPermissionState ps, @NonNull AndroidPackage pkg) {
3142         String pkgName = pkg.getPackageName();
3143         boolean isGranted = false;
3144         int flags = 0;
3145 
3146         int numSourcePerm = sourcePerms.size();
3147         for (int i = 0; i < numSourcePerm; i++) {
3148             String sourcePerm = sourcePerms.valueAt(i);
3149             if (ps.isPermissionGranted(sourcePerm)) {
3150                 if (!isGranted) {
3151                     flags = 0;
3152                 }
3153 
3154                 isGranted = true;
3155                 flags |= ps.getPermissionFlags(sourcePerm);
3156             } else {
3157                 if (!isGranted) {
3158                     flags |= ps.getPermissionFlags(sourcePerm);
3159                 }
3160             }
3161         }
3162 
3163         if (isGranted) {
3164             if (DEBUG_PERMISSIONS) {
3165                 Slog.i(TAG, newPerm + " inherits runtime perm grant from " + sourcePerms
3166                         + " for " + pkgName);
3167             }
3168 
3169             ps.grantPermission(mRegistry.getPermission(newPerm));
3170         }
3171 
3172         // Add permission flags
3173         ps.updatePermissionFlags(mRegistry.getPermission(newPerm), flags, flags);
3174     }
3175 
3176     /**
3177      * When the app has requested legacy storage we might need to update
3178      * {@link android.app.AppOpsManager#OP_LEGACY_STORAGE}. Hence force an update in
3179      * {@link com.android.server.policy.PermissionPolicyService#synchronizePackagePermissionsAndAppOpsForUser(Context, String, int)}
3180      *
3181      * @param pkg The package for which the permissions are updated
3182      * @param replace If the app is being replaced
3183      * @param userIds All user IDs in the system, must be passed in because this method is locked
3184      * @param updatedUserIds The ids of the users that already changed.
3185      *
3186      * @return The ids of the users that are changed
3187      */
3188     private @NonNull int[] checkIfLegacyStorageOpsNeedToBeUpdated(@NonNull AndroidPackage pkg,
3189             boolean replace, @NonNull int[] userIds, @NonNull int[] updatedUserIds) {
3190         if (replace && pkg.isRequestLegacyExternalStorage() && (
3191                 pkg.getRequestedPermissions().contains(READ_EXTERNAL_STORAGE)
3192                         || pkg.getRequestedPermissions().contains(WRITE_EXTERNAL_STORAGE))) {
3193             return userIds.clone();
3194         }
3195 
3196         return updatedUserIds;
3197     }
3198 
3199     /**
3200      * Set the state of a implicit permission that is seen for the first time.
3201      *
3202      * @param origPs The permission state of the package before the split
3203      * @param ps The new permission state
3204      * @param pkg The package the permission belongs to
3205      * @param userId The user ID
3206      * @param updatedUserIds List of users for which the permission state has already been changed
3207      *
3208      * @return  List of users for which the permission state has been changed
3209      */
3210     @GuardedBy("mLock")
3211     private @NonNull int[] setInitialGrantForNewImplicitPermissionsLocked(
3212             @NonNull UidPermissionState origPs, @NonNull UidPermissionState ps,
3213             @NonNull AndroidPackage pkg, @NonNull ArraySet<String> newImplicitPermissions,
3214             @UserIdInt int userId, @NonNull int[] updatedUserIds) {
3215         String pkgName = pkg.getPackageName();
3216         ArrayMap<String, ArraySet<String>> newToSplitPerms = new ArrayMap<>();
3217 
3218         final List<PermissionManager.SplitPermissionInfo> permissionList =
3219                 getSplitPermissionInfos();
3220         int numSplitPerms = permissionList.size();
3221         for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
3222             PermissionManager.SplitPermissionInfo spi = permissionList.get(splitPermNum);
3223 
3224             List<String> newPerms = spi.getNewPermissions();
3225             int numNewPerms = newPerms.size();
3226             for (int newPermNum = 0; newPermNum < numNewPerms; newPermNum++) {
3227                 String newPerm = newPerms.get(newPermNum);
3228 
3229                 ArraySet<String> splitPerms = newToSplitPerms.get(newPerm);
3230                 if (splitPerms == null) {
3231                     splitPerms = new ArraySet<>();
3232                     newToSplitPerms.put(newPerm, splitPerms);
3233                 }
3234 
3235                 splitPerms.add(spi.getSplitPermission());
3236             }
3237         }
3238 
3239         int numNewImplicitPerms = newImplicitPermissions.size();
3240         for (int newImplicitPermNum = 0; newImplicitPermNum < numNewImplicitPerms;
3241                 newImplicitPermNum++) {
3242             String newPerm = newImplicitPermissions.valueAt(newImplicitPermNum);
3243             ArraySet<String> sourcePerms = newToSplitPerms.get(newPerm);
3244 
3245             if (sourcePerms != null) {
3246                 Permission bp = mRegistry.getPermission(newPerm);
3247                 if (bp == null) {
3248                     throw new IllegalStateException("Unknown new permission in split permission: "
3249                             + newPerm);
3250                 }
3251                 if (bp.isRuntime()) {
3252 
3253                     if (!newPerm.equals(Manifest.permission.ACTIVITY_RECOGNITION)) {
3254                         ps.updatePermissionFlags(bp,
3255                                 FLAG_PERMISSION_REVOKE_WHEN_REQUESTED,
3256                                 FLAG_PERMISSION_REVOKE_WHEN_REQUESTED);
3257                     }
3258                     updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
3259 
3260                     if (!origPs.hasPermissionState(sourcePerms)) {
3261                         boolean inheritsFromInstallPerm = false;
3262                         for (int sourcePermNum = 0; sourcePermNum < sourcePerms.size();
3263                                 sourcePermNum++) {
3264                             final String sourcePerm = sourcePerms.valueAt(sourcePermNum);
3265                             Permission sourceBp = mRegistry.getPermission(sourcePerm);
3266                             if (sourceBp == null) {
3267                                 throw new IllegalStateException("Unknown source permission in split"
3268                                         + " permission: " + sourcePerm);
3269                             }
3270                             if (!sourceBp.isRuntime()) {
3271                                 inheritsFromInstallPerm = true;
3272                                 break;
3273                             }
3274                         }
3275 
3276                         if (!inheritsFromInstallPerm) {
3277                             // Both permissions are new so nothing to inherit.
3278                             if (DEBUG_PERMISSIONS) {
3279                                 Slog.i(TAG, newPerm + " does not inherit from " + sourcePerms
3280                                         + " for " + pkgName + " as split permission is also new");
3281                             }
3282                             continue;
3283                         }
3284                     }
3285 
3286                     // Inherit from new install or existing runtime permissions
3287                     inheritPermissionStateToNewImplicitPermissionLocked(sourcePerms, newPerm, ps,
3288                             pkg);
3289                 }
3290             }
3291         }
3292 
3293         return updatedUserIds;
3294     }
3295 
3296     @NonNull
3297     @Override
3298     public List<SplitPermissionInfoParcelable> getSplitPermissions() {
3299         return PermissionManager.splitPermissionInfoListToParcelableList(getSplitPermissionInfos());
3300     }
3301 
3302     @NonNull
3303     private List<PermissionManager.SplitPermissionInfo> getSplitPermissionInfos() {
3304         return SystemConfig.getInstance().getSplitPermissions();
3305     }
3306 
3307     @NonNull
3308     private OneTimePermissionUserManager getOneTimePermissionUserManager(@UserIdInt int userId) {
3309         OneTimePermissionUserManager oneTimePermissionUserManager;
3310         synchronized (mLock) {
3311             oneTimePermissionUserManager = mOneTimePermissionUserManagers.get(userId);
3312             if (oneTimePermissionUserManager != null) {
3313                 return oneTimePermissionUserManager;
3314             }
3315         }
3316         // We cannot create a new instance of OneTimePermissionUserManager while holding our own
3317         // lock, which may lead to a deadlock with the package manager lock. So we do it in a
3318         // retry-like way, and just discard the newly created instance if someone else managed to be
3319         // a little bit faster than us when we dropped our own lock.
3320         final OneTimePermissionUserManager newOneTimePermissionUserManager =
3321                 new OneTimePermissionUserManager(mContext.createContextAsUser(UserHandle.of(userId),
3322                         /*flags*/ 0));
3323         synchronized (mLock) {
3324             oneTimePermissionUserManager = mOneTimePermissionUserManagers.get(userId);
3325             if (oneTimePermissionUserManager != null) {
3326                 return oneTimePermissionUserManager;
3327             }
3328             oneTimePermissionUserManager = newOneTimePermissionUserManager;
3329             mOneTimePermissionUserManagers.put(userId, oneTimePermissionUserManager);
3330         }
3331         oneTimePermissionUserManager.registerUninstallListener();
3332         return oneTimePermissionUserManager;
3333     }
3334 
3335     @Override
3336     public void startOneTimePermissionSession(String packageName, @UserIdInt int userId,
3337             long timeoutMillis, int importanceToResetTimer, int importanceToKeepSessionAlive) {
3338         mContext.enforceCallingPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS,
3339                 "Must hold " + Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS
3340                         + " to register permissions as one time.");
3341         Objects.requireNonNull(packageName);
3342 
3343         final long token = Binder.clearCallingIdentity();
3344         try {
3345             getOneTimePermissionUserManager(userId).startPackageOneTimeSession(packageName,
3346                     timeoutMillis, importanceToResetTimer, importanceToKeepSessionAlive);
3347         } finally {
3348             Binder.restoreCallingIdentity(token);
3349         }
3350     }
3351 
3352     @Override
3353     public void stopOneTimePermissionSession(String packageName, @UserIdInt int userId) {
3354         mContext.enforceCallingPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS,
3355                 "Must hold " + Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS
3356                         + " to remove permissions as one time.");
3357         Objects.requireNonNull(packageName);
3358 
3359         final long token = Binder.clearCallingIdentity();
3360         try {
3361             getOneTimePermissionUserManager(userId).stopPackageOneTimeSession(packageName);
3362         } finally {
3363             Binder.restoreCallingIdentity(token);
3364         }
3365     }
3366 
3367     @Override
3368     public void registerAttributionSource(@NonNull AttributionSourceState source) {
3369         mAttributionSourceRegistry
3370                 .registerAttributionSource(new AttributionSource(source));
3371     }
3372 
3373     @Override
3374     public boolean isRegisteredAttributionSource(@NonNull AttributionSourceState source) {
3375         return mAttributionSourceRegistry
3376                 .isRegisteredAttributionSource(new AttributionSource(source));
3377     }
3378 
3379     @Override
3380     public List<String> getAutoRevokeExemptionRequestedPackages(int userId) {
3381         return getPackagesWithAutoRevokePolicy(AUTO_REVOKE_DISCOURAGED, userId);
3382     }
3383 
3384     @Override
3385     public List<String> getAutoRevokeExemptionGrantedPackages(int userId) {
3386         return getPackagesWithAutoRevokePolicy(AUTO_REVOKE_DISALLOWED, userId);
3387     }
3388 
3389     @NonNull
3390     private List<String> getPackagesWithAutoRevokePolicy(int autoRevokePolicy, int userId) {
3391         mContext.enforceCallingPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
3392                 "Must hold " + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY);
3393 
3394         List<String> result = new ArrayList<>();
3395         mPackageManagerInt.forEachInstalledPackage(pkg -> {
3396             if (pkg.getAutoRevokePermissions() == autoRevokePolicy) {
3397                 result.add(pkg.getPackageName());
3398             }
3399         }, userId);
3400         return result;
3401     }
3402 
3403     private static boolean isNewPlatformPermissionForPackage(String perm, AndroidPackage pkg) {
3404         boolean allowed = false;
3405         final int NP = PackageParser.NEW_PERMISSIONS.length;
3406         for (int ip=0; ip<NP; ip++) {
3407             final PackageParser.NewPermissionInfo npi
3408                     = PackageParser.NEW_PERMISSIONS[ip];
3409             if (npi.name.equals(perm)
3410                     && pkg.getTargetSdkVersion() < npi.sdkVersion) {
3411                 allowed = true;
3412                 Log.i(TAG, "Auto-granting " + perm + " to old pkg "
3413                         + pkg.getPackageName());
3414                 break;
3415             }
3416         }
3417         return allowed;
3418     }
3419 
3420     private boolean checkPrivilegedPermissionAllowlist(@NonNull AndroidPackage pkg,
3421             @NonNull PackageSetting packageSetting, @NonNull Permission permission) {
3422         if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE) {
3423             return true;
3424         }
3425         final String packageName = pkg.getPackageName();
3426         if (Objects.equals(packageName, PLATFORM_PACKAGE_NAME)) {
3427             return true;
3428         }
3429         if (!pkg.isPrivileged()) {
3430             return true;
3431         }
3432         if (!mPrivilegedPermissionAllowlistSourcePackageNames
3433                 .contains(permission.getPackageName())) {
3434             return true;
3435         }
3436         final String permissionName = permission.getName();
3437         if (isInSystemConfigPrivAppPermissions(pkg, permissionName)) {
3438             return true;
3439         }
3440         if (isInSystemConfigPrivAppDenyPermissions(pkg, permissionName)) {
3441             return false;
3442         }
3443         // Updated system apps do not need to be allowlisted
3444         if (packageSetting.getPkgState().isUpdatedSystemApp()) {
3445             // Let shouldGrantPermissionByProtectionFlags() decide whether the privileged permission
3446             // can be granted, because an updated system app may be in a shared UID, and in case a
3447             // new privileged permission is requested by the updated system app but not the factory
3448             // app, although this app and permission combination isn't in the allowlist and can't
3449             // get the permission this way, other apps in the shared UID may still get it. A proper
3450             // fix for this would be to perform the reconciliation by UID, but for now let's keep
3451             // the old workaround working, which is to keep granted privileged permissions still
3452             // granted.
3453             return true;
3454         }
3455         // Only enforce the allowlist on boot
3456         if (!mSystemReady) {
3457             final ApexManager apexManager = ApexManager.getInstance();
3458             final String containingApexPackageName =
3459                     apexManager.getActiveApexPackageNameContainingPackage(packageName);
3460             final boolean isInUpdatedApex = containingApexPackageName != null
3461                     && !apexManager.isFactory(apexManager.getPackageInfo(containingApexPackageName,
3462                     MATCH_ACTIVE_PACKAGE));
3463             // Apps that are in updated apexs' do not need to be allowlisted
3464             if (!isInUpdatedApex) {
3465                 Slog.w(TAG, "Privileged permission " + permissionName + " for package "
3466                         + packageName + " (" + pkg.getPath()
3467                         + ") not in privapp-permissions allowlist");
3468                 if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
3469                     synchronized (mLock) {
3470                         if (mPrivappPermissionsViolations == null) {
3471                             mPrivappPermissionsViolations = new ArraySet<>();
3472                         }
3473                         mPrivappPermissionsViolations.add(packageName + " (" + pkg.getPath() + "): "
3474                                 + permissionName);
3475                     }
3476                 }
3477             }
3478         }
3479         return !RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE;
3480     }
3481 
3482     private boolean isInSystemConfigPrivAppPermissions(@NonNull AndroidPackage pkg,
3483             @NonNull String permission) {
3484         final SystemConfig systemConfig = SystemConfig.getInstance();
3485         final Set<String> permissions;
3486         if (pkg.isVendor()) {
3487             permissions = systemConfig.getVendorPrivAppPermissions(pkg.getPackageName());
3488         } else if (pkg.isProduct()) {
3489             permissions = systemConfig.getProductPrivAppPermissions(pkg.getPackageName());
3490         } else if (pkg.isSystemExt()) {
3491             permissions = systemConfig.getSystemExtPrivAppPermissions(pkg.getPackageName());
3492         } else {
3493             permissions = systemConfig.getPrivAppPermissions(pkg.getPackageName());
3494         }
3495         return CollectionUtils.contains(permissions, permission);
3496     }
3497 
3498     private boolean isInSystemConfigPrivAppDenyPermissions(@NonNull AndroidPackage pkg,
3499             @NonNull String permission) {
3500         final SystemConfig systemConfig = SystemConfig.getInstance();
3501         final Set<String> permissions;
3502         if (pkg.isVendor()) {
3503             permissions = systemConfig.getVendorPrivAppDenyPermissions(pkg.getPackageName());
3504         } else if (pkg.isProduct()) {
3505             permissions = systemConfig.getProductPrivAppDenyPermissions(pkg.getPackageName());
3506         } else if (pkg.isSystemExt()) {
3507             permissions = systemConfig.getSystemExtPrivAppDenyPermissions(pkg.getPackageName());
3508         } else {
3509             permissions = systemConfig.getPrivAppDenyPermissions(pkg.getPackageName());
3510         }
3511         return CollectionUtils.contains(permissions, permission);
3512     }
3513 
3514     private boolean shouldGrantPermissionBySignature(@NonNull AndroidPackage pkg,
3515             @NonNull Permission bp) {
3516         // expect single system package
3517         String systemPackageName = ArrayUtils.firstOrNull(mPackageManagerInt.getKnownPackageNames(
3518                 PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM));
3519         final AndroidPackage systemPackage =
3520                 mPackageManagerInt.getPackage(systemPackageName);
3521         // check if the package is allow to use this signature permission.  A package is allowed to
3522         // use a signature permission if:
3523         //     - it has the same set of signing certificates as the source package
3524         //     - or its signing certificate was rotated from the source package's certificate
3525         //     - or its signing certificate is a previous signing certificate of the defining
3526         //       package, and the defining package still trusts the old certificate for permissions
3527         //     - or it shares a common signing certificate in its lineage with the defining package,
3528         //       and the defining package still trusts the old certificate for permissions
3529         //     - or it shares the above relationships with the system package
3530         final PackageParser.SigningDetails sourceSigningDetails =
3531                 getSourcePackageSigningDetails(bp);
3532         return sourceSigningDetails.hasCommonSignerWithCapability(
3533                         pkg.getSigningDetails(),
3534                         PackageParser.SigningDetails.CertCapabilities.PERMISSION)
3535                 || pkg.getSigningDetails().hasAncestorOrSelf(systemPackage.getSigningDetails())
3536                 || systemPackage.getSigningDetails().checkCapability(
3537                         pkg.getSigningDetails(),
3538                         PackageParser.SigningDetails.CertCapabilities.PERMISSION);
3539     }
3540 
3541     private boolean shouldGrantPermissionByProtectionFlags(@NonNull AndroidPackage pkg,
3542             @NonNull PackageSetting pkgSetting, @NonNull Permission bp,
3543             @NonNull ArraySet<String> shouldGrantPrivilegedPermissionIfWasGranted) {
3544         boolean allowed = false;
3545         final boolean isPrivilegedPermission = bp.isPrivileged();
3546         final boolean isOemPermission = bp.isOem();
3547         if (!allowed && (isPrivilegedPermission || isOemPermission) && pkg.isSystem()) {
3548             final String permissionName = bp.getName();
3549             // For updated system applications, a privileged/oem permission
3550             // is granted only if it had been defined by the original application.
3551             if (pkgSetting.getPkgState().isUpdatedSystemApp()) {
3552                 final PackageSetting disabledPs = mPackageManagerInt
3553                         .getDisabledSystemPackage(pkg.getPackageName());
3554                 final AndroidPackage disabledPkg = disabledPs == null ? null : disabledPs.pkg;
3555                 if (disabledPkg != null
3556                         && ((isPrivilegedPermission && disabledPkg.isPrivileged())
3557                         || (isOemPermission && canGrantOemPermission(disabledPkg,
3558                                 permissionName)))) {
3559                     if (disabledPkg.getRequestedPermissions().contains(permissionName)) {
3560                         allowed = true;
3561                     } else {
3562                         // If the original was granted this permission, we take
3563                         // that grant decision as read and propagate it to the
3564                         // update.
3565                         shouldGrantPrivilegedPermissionIfWasGranted.add(permissionName);
3566                     }
3567                 }
3568             } else {
3569                 allowed = (isPrivilegedPermission && pkg.isPrivileged())
3570                         || (isOemPermission && canGrantOemPermission(pkg, permissionName));
3571             }
3572             // In any case, don't grant a privileged permission to privileged vendor apps, if
3573             // the permission's protectionLevel does not have the extra 'vendorPrivileged'
3574             // flag.
3575             if (allowed && isPrivilegedPermission && !bp.isVendorPrivileged() && pkg.isVendor()) {
3576                 Slog.w(TAG, "Permission " + permissionName
3577                         + " cannot be granted to privileged vendor apk " + pkg.getPackageName()
3578                         + " because it isn't a 'vendorPrivileged' permission.");
3579                 allowed = false;
3580             }
3581         }
3582         if (!allowed && bp.isPre23() && pkg.getTargetSdkVersion() < Build.VERSION_CODES.M) {
3583             // If this was a previously normal/dangerous permission that got moved
3584             // to a system permission as part of the runtime permission redesign, then
3585             // we still want to blindly grant it to old apps.
3586             allowed = true;
3587         }
3588         // TODO (moltmann): The installer now shares the platforms signature. Hence it does not
3589         //                  need a separate flag anymore. Hence we need to check which
3590         //                  permissions are needed by the permission controller
3591         if (!allowed && bp.isInstaller()
3592                 && (ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3593                         PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM),
3594                 pkg.getPackageName()) || ArrayUtils.contains(
3595                         mPackageManagerInt.getKnownPackageNames(
3596                                 PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER,
3597                 UserHandle.USER_SYSTEM), pkg.getPackageName()))) {
3598             // If this permission is to be granted to the system installer and
3599             // this app is an installer, then it gets the permission.
3600             allowed = true;
3601         }
3602         if (!allowed && bp.isVerifier()
3603                 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3604                         PackageManagerInternal.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM),
3605                 pkg.getPackageName())) {
3606             // If this permission is to be granted to the system verifier and
3607             // this app is a verifier, then it gets the permission.
3608             allowed = true;
3609         }
3610         if (!allowed && bp.isPreInstalled()
3611                 && pkg.isSystem()) {
3612             // Any pre-installed system app is allowed to get this permission.
3613             allowed = true;
3614         }
3615         if (!allowed && bp.isKnownSigner()) {
3616             // If the permission is to be granted to a known signer then check if any of this
3617             // app's signing certificates are in the trusted certificate digest Set.
3618             allowed = pkg.getSigningDetails().hasAncestorOrSelfWithDigest(bp.getKnownCerts());
3619         }
3620         // Deferred to be checked under permission data lock inside restorePermissionState().
3621         //if (!allowed && bp.isDevelopment()) {
3622         //    // For development permissions, a development permission
3623         //    // is granted only if it was already granted.
3624         //    allowed = origPermissions.isPermissionGranted(permissionName);
3625         //}
3626         if (!allowed && bp.isSetup()
3627                 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3628                         PackageManagerInternal.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM),
3629                 pkg.getPackageName())) {
3630             // If this permission is to be granted to the system setup wizard and
3631             // this app is a setup wizard, then it gets the permission.
3632             allowed = true;
3633         }
3634         if (!allowed && bp.isSystemTextClassifier()
3635                 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3636                         PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER,
3637                 UserHandle.USER_SYSTEM), pkg.getPackageName())) {
3638             // Special permissions for the system default text classifier.
3639             allowed = true;
3640         }
3641         if (!allowed && bp.isConfigurator()
3642                 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3643                         PackageManagerInternal.PACKAGE_CONFIGURATOR,
3644                 UserHandle.USER_SYSTEM), pkg.getPackageName())) {
3645             // Special permissions for the device configurator.
3646             allowed = true;
3647         }
3648         if (!allowed && bp.isDocumenter()
3649                 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3650                         PackageManagerInternal.PACKAGE_DOCUMENTER, UserHandle.USER_SYSTEM),
3651                 pkg.getPackageName())) {
3652             // If this permission is to be granted to the documenter and
3653             // this app is the documenter, then it gets the permission.
3654             allowed = true;
3655         }
3656         if (!allowed && bp.isIncidentReportApprover()
3657                 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3658                         PackageManagerInternal.PACKAGE_INCIDENT_REPORT_APPROVER,
3659                 UserHandle.USER_SYSTEM), pkg.getPackageName())) {
3660             // If this permission is to be granted to the incident report approver and
3661             // this app is the incident report approver, then it gets the permission.
3662             allowed = true;
3663         }
3664         if (!allowed && bp.isAppPredictor()
3665                 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3666                         PackageManagerInternal.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM),
3667                 pkg.getPackageName())) {
3668             // Special permissions for the system app predictor.
3669             allowed = true;
3670         }
3671         if (!allowed && bp.isCompanion()
3672                 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3673                     PackageManagerInternal.PACKAGE_COMPANION, UserHandle.USER_SYSTEM),
3674                 pkg.getPackageName())) {
3675             // Special permissions for the system companion device manager.
3676             allowed = true;
3677         }
3678         if (!allowed && bp.isRetailDemo()
3679                 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3680                         PackageManagerInternal.PACKAGE_RETAIL_DEMO, UserHandle.USER_SYSTEM),
3681                 pkg.getPackageName()) && isProfileOwner(pkg.getUid())) {
3682             // Special permission granted only to the OEM specified retail demo app
3683             allowed = true;
3684         }
3685         if (!allowed && bp.isRecents()
3686                 && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
3687                 PackageManagerInternal.PACKAGE_RECENTS, UserHandle.USER_SYSTEM),
3688                 pkg.getPackageName())) {
3689             // Special permission for the recents app.
3690             allowed = true;
3691         }
3692         return allowed;
3693     }
3694 
3695     @NonNull
3696     private PackageParser.SigningDetails getSourcePackageSigningDetails(
3697             @NonNull Permission bp) {
3698         final PackageSetting ps = getSourcePackageSetting(bp);
3699         if (ps == null) {
3700             return PackageParser.SigningDetails.UNKNOWN;
3701         }
3702         return ps.getSigningDetails();
3703     }
3704 
3705     @Nullable
3706     private PackageSetting getSourcePackageSetting(@NonNull Permission bp) {
3707         final String sourcePackageName = bp.getPackageName();
3708         return mPackageManagerInt.getPackageSetting(sourcePackageName);
3709     }
3710 
3711     private static boolean canGrantOemPermission(AndroidPackage pkg, String permission) {
3712         if (!pkg.isOem()) {
3713             return false;
3714         }
3715         // all oem permissions must explicitly be granted or denied
3716         final Boolean granted =
3717                 SystemConfig.getInstance().getOemPermissions(pkg.getPackageName()).get(permission);
3718         if (granted == null) {
3719             throw new IllegalStateException("OEM permission" + permission + " requested by package "
3720                     + pkg.getPackageName() + " must be explicitly declared granted or not");
3721         }
3722         return Boolean.TRUE == granted;
3723     }
3724 
3725     private static boolean isProfileOwner(int uid) {
3726         DevicePolicyManagerInternal dpmInternal =
3727                 LocalServices.getService(DevicePolicyManagerInternal.class);
3728         //TODO(b/169395065) Figure out if this flow makes sense in Device Owner mode.
3729         if (dpmInternal != null) {
3730             return dpmInternal.isActiveProfileOwner(uid) || dpmInternal.isActiveDeviceOwner(uid);
3731         }
3732         return false;
3733     }
3734 
3735     private boolean isPermissionsReviewRequiredInternal(@NonNull String packageName,
3736             @UserIdInt int userId) {
3737         final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
3738         if (pkg == null) {
3739             return false;
3740         }
3741 
3742         // Permission review applies only to apps not supporting the new permission model.
3743         if (pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M) {
3744             return false;
3745         }
3746 
3747         // Legacy apps have the permission and get user consent on launch.
3748         synchronized (mLock) {
3749             final UidPermissionState uidState = getUidStateLocked(pkg, userId);
3750             if (uidState == null) {
3751                 Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
3752                         + userId);
3753                 return false;
3754             }
3755             return uidState.isPermissionsReviewRequired();
3756         }
3757     }
3758 
3759     private void grantRequestedRuntimePermissionsInternal(@NonNull AndroidPackage pkg,
3760             @Nullable List<String> permissions, int userId) {
3761         final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
3762                 | PackageManager.FLAG_PERMISSION_POLICY_FIXED;
3763 
3764         final int compatFlags = PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
3765                 | PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
3766 
3767         final boolean supportsRuntimePermissions = pkg.getTargetSdkVersion()
3768                 >= Build.VERSION_CODES.M;
3769 
3770         final boolean instantApp = mPackageManagerInt.isInstantApp(pkg.getPackageName(), userId);
3771 
3772         final int myUid = Process.myUid();
3773 
3774         for (String permission : pkg.getRequestedPermissions()) {
3775             final boolean shouldGrantPermission;
3776             synchronized (mLock) {
3777                 final Permission bp = mRegistry.getPermission(permission);
3778                 shouldGrantPermission = bp != null && (bp.isRuntime() || bp.isDevelopment())
3779                         && (!instantApp || bp.isInstant())
3780                         && (supportsRuntimePermissions || !bp.isRuntimeOnly())
3781                         && (permissions == null || permissions.contains(permission));
3782             }
3783             if (shouldGrantPermission) {
3784                 final int flags = getPermissionFlagsInternal(pkg.getPackageName(), permission,
3785                         myUid, userId);
3786                 if (supportsRuntimePermissions) {
3787                     // Installer cannot change immutable permissions.
3788                     if ((flags & immutableFlags) == 0) {
3789                         grantRuntimePermissionInternal(pkg.getPackageName(), permission, false,
3790                                 myUid, userId, mDefaultPermissionCallback);
3791                     }
3792                 } else {
3793                     // In permission review mode we clear the review flag and the revoked compat
3794                     // flag when we are asked to install the app with all permissions granted.
3795                     if ((flags & compatFlags) != 0) {
3796                         updatePermissionFlagsInternal(pkg.getPackageName(), permission, compatFlags,
3797                                 0, myUid, userId, false, mDefaultPermissionCallback);
3798                     }
3799                 }
3800             }
3801         }
3802     }
3803 
3804     private void setAllowlistedRestrictedPermissionsInternal(@NonNull AndroidPackage pkg,
3805             @Nullable List<String> permissions, @PermissionWhitelistFlags int allowlistFlags,
3806             @UserIdInt int userId) {
3807         ArraySet<String> oldGrantedRestrictedPermissions = null;
3808         boolean updatePermissions = false;
3809         final int permissionCount = pkg.getRequestedPermissions().size();
3810         final int myUid = Process.myUid();
3811 
3812         for (int j = 0; j < permissionCount; j++) {
3813             final String permissionName = pkg.getRequestedPermissions().get(j);
3814 
3815             final boolean isGranted;
3816             synchronized (mLock) {
3817                 final Permission bp = mRegistry.getPermission(permissionName);
3818                 if (bp == null || !bp.isHardOrSoftRestricted()) {
3819                     continue;
3820                 }
3821 
3822                 final UidPermissionState uidState = getUidStateLocked(pkg, userId);
3823                 if (uidState == null) {
3824                     Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName()
3825                             + " and user " + userId);
3826                     continue;
3827                 }
3828                 isGranted = uidState.isPermissionGranted(permissionName);
3829             }
3830 
3831             if (isGranted) {
3832                 if (oldGrantedRestrictedPermissions == null) {
3833                     oldGrantedRestrictedPermissions = new ArraySet<>();
3834                 }
3835                 oldGrantedRestrictedPermissions.add(permissionName);
3836             }
3837 
3838             final int oldFlags = getPermissionFlagsInternal(pkg.getPackageName(), permissionName,
3839                     myUid, userId);
3840 
3841             int newFlags = oldFlags;
3842             int mask = 0;
3843             int allowlistFlagsCopy = allowlistFlags;
3844             while (allowlistFlagsCopy != 0) {
3845                 final int flag = 1 << Integer.numberOfTrailingZeros(allowlistFlagsCopy);
3846                 allowlistFlagsCopy &= ~flag;
3847                 switch (flag) {
3848                     case FLAG_PERMISSION_WHITELIST_SYSTEM: {
3849                         mask |= FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
3850                         if (permissions != null && permissions.contains(permissionName)) {
3851                             newFlags |= FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
3852                         } else {
3853                             newFlags &= ~FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
3854                         }
3855                     }
3856                     break;
3857                     case FLAG_PERMISSION_WHITELIST_UPGRADE: {
3858                         mask |= FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
3859                         if (permissions != null && permissions.contains(permissionName)) {
3860                             newFlags |= FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
3861                         } else {
3862                             newFlags &= ~FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
3863                         }
3864                     }
3865                     break;
3866                     case FLAG_PERMISSION_WHITELIST_INSTALLER: {
3867                         mask |= FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
3868                         if (permissions != null && permissions.contains(permissionName)) {
3869                             newFlags |= FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
3870                         } else {
3871                             newFlags &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
3872                         }
3873                     }
3874                     break;
3875                 }
3876             }
3877 
3878             if (oldFlags == newFlags) {
3879                 continue;
3880             }
3881 
3882             updatePermissions = true;
3883 
3884             final boolean wasAllowlisted = (oldFlags
3885                     & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
3886             final boolean isAllowlisted = (newFlags
3887                     & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
3888 
3889             // If the permission is policy fixed as granted but it is no longer
3890             // on any of the allowlists we need to clear the policy fixed flag
3891             // as allowlisting trumps policy i.e. policy cannot grant a non
3892             // grantable permission.
3893             if ((oldFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
3894                 if (!isAllowlisted && isGranted) {
3895                     mask |= PackageManager.FLAG_PERMISSION_POLICY_FIXED;
3896                     newFlags &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED;
3897                 }
3898             }
3899 
3900             // If we are allowlisting an app that does not support runtime permissions
3901             // we need to make sure it goes through the permission review UI at launch.
3902             if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M
3903                     && !wasAllowlisted && isAllowlisted) {
3904                 mask |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
3905                 newFlags |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
3906             }
3907 
3908             updatePermissionFlagsInternal(pkg.getPackageName(), permissionName, mask, newFlags,
3909                     myUid, userId, false, null /*callback*/);
3910         }
3911 
3912         if (updatePermissions) {
3913             // Update permission of this app to take into account the new allowlist state.
3914             restorePermissionState(pkg, false, pkg.getPackageName(), mDefaultPermissionCallback,
3915                     userId);
3916 
3917             // If this resulted in losing a permission we need to kill the app.
3918             if (oldGrantedRestrictedPermissions == null) {
3919                 return;
3920             }
3921 
3922             final int oldGrantedCount = oldGrantedRestrictedPermissions.size();
3923             for (int j = 0; j < oldGrantedCount; j++) {
3924                 final String permissionName = oldGrantedRestrictedPermissions.valueAt(j);
3925                 // Sometimes we create a new permission state instance during update.
3926                 final boolean isGranted;
3927                 synchronized (mLock) {
3928                     final UidPermissionState uidState = getUidStateLocked(pkg, userId);
3929                     if (uidState == null) {
3930                         Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName()
3931                                 + " and user " + userId);
3932                         continue;
3933                     }
3934                     isGranted = uidState.isPermissionGranted(permissionName);
3935                 }
3936                 if (!isGranted) {
3937                     mDefaultPermissionCallback.onPermissionRevoked(pkg.getUid(), userId, null);
3938                     break;
3939                 }
3940             }
3941         }
3942     }
3943 
3944     @UserIdInt
3945     private int revokeSharedUserPermissionsForDeletedPackageInternal(
3946             @Nullable AndroidPackage pkg, @NonNull List<AndroidPackage> sharedUserPkgs,
3947             @UserIdInt int userId) {
3948         if (pkg == null) {
3949             Slog.i(TAG, "Trying to update info for null package. Just ignoring");
3950             return UserHandle.USER_NULL;
3951         }
3952 
3953         // No shared user packages
3954         if (sharedUserPkgs.isEmpty()) {
3955             return UserHandle.USER_NULL;
3956         }
3957 
3958         int affectedUserId = UserHandle.USER_NULL;
3959         // Update permissions
3960         for (String eachPerm : pkg.getRequestedPermissions()) {
3961             // Check if another package in the shared user needs the permission.
3962             boolean used = false;
3963             for (AndroidPackage sharedUserpkg : sharedUserPkgs) {
3964                 if (sharedUserpkg != null
3965                         && !sharedUserpkg.getPackageName().equals(pkg.getPackageName())
3966                         && sharedUserpkg.getRequestedPermissions().contains(eachPerm)) {
3967                     used = true;
3968                     break;
3969                 }
3970             }
3971             if (used) {
3972                 continue;
3973             }
3974 
3975             PackageSetting disabledPs = mPackageManagerInt.getDisabledSystemPackage(
3976                     pkg.getPackageName());
3977 
3978             // If the package is shadowing is a disabled system package,
3979             // do not drop permissions that the shadowed package requests.
3980             if (disabledPs != null) {
3981                 boolean reqByDisabledSysPkg = false;
3982                 for (String permission : disabledPs.pkg.getRequestedPermissions()) {
3983                     if (permission.equals(eachPerm)) {
3984                         reqByDisabledSysPkg = true;
3985                         break;
3986                     }
3987                 }
3988                 if (reqByDisabledSysPkg) {
3989                     continue;
3990                 }
3991             }
3992 
3993             synchronized (mLock) {
3994                 UidPermissionState uidState = getUidStateLocked(pkg, userId);
3995                 if (uidState == null) {
3996                     Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName()
3997                             + " and user " + userId);
3998                     continue;
3999                 }
4000 
4001                 Permission bp = mRegistry.getPermission(eachPerm);
4002                 if (bp == null) {
4003                     continue;
4004                 }
4005 
4006                 // TODO(zhanghai): Why are we only killing the UID when GIDs changed, instead of any
4007                 //  permission change?
4008                 if (uidState.removePermissionState(bp.getName()) && bp.hasGids()) {
4009                     affectedUserId = userId;
4010                 }
4011             }
4012         }
4013 
4014         return affectedUserId;
4015     }
4016 
4017     @GuardedBy("mLock")
4018     private boolean revokeUnusedSharedUserPermissionsLocked(
4019             List<AndroidPackage> pkgList, UidPermissionState uidState) {
4020         // Collect all used permissions in the UID
4021         final ArraySet<String> usedPermissions = new ArraySet<>();
4022         if (pkgList == null || pkgList.size() == 0) {
4023             return false;
4024         }
4025         for (AndroidPackage pkg : pkgList) {
4026             if (pkg.getRequestedPermissions().isEmpty()) {
4027                 continue;
4028             }
4029             final int requestedPermCount = pkg.getRequestedPermissions().size();
4030             for (int j = 0; j < requestedPermCount; j++) {
4031                 String permission = pkg.getRequestedPermissions().get(j);
4032                 Permission bp = mRegistry.getPermission(permission);
4033                 if (bp != null) {
4034                     usedPermissions.add(permission);
4035                 }
4036             }
4037         }
4038 
4039         boolean runtimePermissionChanged = false;
4040 
4041         // Prune permissions
4042         final List<PermissionState> permissionStates = uidState.getPermissionStates();
4043         final int permissionStatesSize = permissionStates.size();
4044         for (int i = permissionStatesSize - 1; i >= 0; i--) {
4045             PermissionState permissionState = permissionStates.get(i);
4046             if (!usedPermissions.contains(permissionState.getName())) {
4047                 Permission bp = mRegistry.getPermission(permissionState.getName());
4048                 if (bp != null) {
4049                     if (uidState.removePermissionState(bp.getName()) && bp.isRuntime()) {
4050                         runtimePermissionChanged = true;
4051                     }
4052                 }
4053             }
4054         }
4055 
4056         return runtimePermissionChanged;
4057     }
4058 
4059     /**
4060      * Update permissions when a package changed.
4061      *
4062      * <p><ol>
4063      *     <li>Reconsider the ownership of permission</li>
4064      *     <li>Update the state (grant, flags) of the permissions</li>
4065      * </ol>
4066      *
4067      * @param packageName The package that is updated
4068      * @param pkg The package that is updated, or {@code null} if package is deleted
4069      */
4070     private void updatePermissions(@NonNull String packageName, @Nullable AndroidPackage pkg) {
4071         // If the package is being deleted, update the permissions of all the apps
4072         final int flags =
4073                 (pkg == null ? UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG
4074                         : UPDATE_PERMISSIONS_REPLACE_PKG);
4075         updatePermissions(
4076                 packageName, pkg, getVolumeUuidForPackage(pkg), flags, mDefaultPermissionCallback);
4077     }
4078 
4079     /**
4080      * Update all permissions for all apps.
4081      *
4082      * <p><ol>
4083      *     <li>Reconsider the ownership of permission</li>
4084      *     <li>Update the state (grant, flags) of the permissions</li>
4085      * </ol>
4086      *
4087      * @param volumeUuid The volume UUID of the packages to be updated
4088      * @param fingerprintChanged whether the current build fingerprint is different from what it was
4089      *                           when this volume was last mounted
4090      */
4091     private void updateAllPermissions(@NonNull String volumeUuid, boolean fingerprintChanged) {
4092         PackageManager.corkPackageInfoCache();  // Prevent invalidation storm
4093         try {
4094             final int flags = UPDATE_PERMISSIONS_ALL |
4095                     (fingerprintChanged
4096                             ? UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL
4097                             : 0);
4098             updatePermissions(null, null, volumeUuid, flags, mDefaultPermissionCallback);
4099         } finally {
4100             PackageManager.uncorkPackageInfoCache();
4101         }
4102     }
4103 
4104     /**
4105      * Update all packages on the volume, <u>beside</u> the changing package. If the changing
4106      * package is set too, all packages are updated.
4107      */
4108     private static final int UPDATE_PERMISSIONS_ALL = 1 << 0;
4109     /** The changing package is replaced. Requires the changing package to be set */
4110     private static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1 << 1;
4111     /**
4112      * Schedule all packages <u>beside</u> the changing package for replacement. Requires
4113      * UPDATE_PERMISSIONS_ALL to be set
4114      */
4115     private static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1 << 2;
4116 
4117     @IntDef(flag = true, prefix = { "UPDATE_PERMISSIONS_" }, value = {
4118             UPDATE_PERMISSIONS_ALL, UPDATE_PERMISSIONS_REPLACE_PKG,
4119             UPDATE_PERMISSIONS_REPLACE_ALL })
4120     @Retention(RetentionPolicy.SOURCE)
4121     private @interface UpdatePermissionFlags {}
4122 
4123     /**
4124      * Update permissions when packages changed.
4125      *
4126      * <p><ol>
4127      *     <li>Reconsider the ownership of permission</li>
4128      *     <li>Update the state (grant, flags) of the permissions</li>
4129      * </ol>
4130      *
4131      * <p>Meaning of combination of package parameters:
4132      * <table>
4133      *     <tr><th></th><th>changingPkgName != null</th><th>changingPkgName == null</th></tr>
4134      *     <tr><th>changingPkg != null</th><td>package is updated</td><td>invalid</td></tr>
4135      *     <tr><th>changingPkg == null</th><td>package is deleted</td><td>all packages are
4136      *                                                                    updated</td></tr>
4137      * </table>
4138      *
4139      * @param changingPkgName The package that is updated, or {@code null} if all packages should be
4140      *                    updated
4141      * @param changingPkg The package that is updated, or {@code null} if all packages should be
4142      *                    updated or package is deleted
4143      * @param replaceVolumeUuid The volume of the packages to be updated are on, {@code null} for
4144      *                          all volumes
4145      * @param flags Control permission for which apps should be updated
4146      * @param callback Callback to call after permission changes
4147      */
4148     private void updatePermissions(final @Nullable String changingPkgName,
4149             final @Nullable AndroidPackage changingPkg,
4150             final @Nullable String replaceVolumeUuid,
4151             @UpdatePermissionFlags int flags,
4152             final @Nullable PermissionCallback callback) {
4153         // TODO: Most of the methods exposing BasePermission internals [source package name,
4154         // etc..] shouldn't be needed. Instead, when we've parsed a permission that doesn't
4155         // have package settings, we should make note of it elsewhere [map between
4156         // source package name and BasePermission] and cycle through that here. Then we
4157         // define a single method on BasePermission that takes a PackageSetting, changing
4158         // package name and a package.
4159         // NOTE: With this approach, we also don't need to tree trees differently than
4160         // normal permissions. Today, we need two separate loops because these BasePermission
4161         // objects are stored separately.
4162         // Make sure there are no dangling permission trees.
4163         boolean permissionTreesSourcePackageChanged = updatePermissionTreeSourcePackage(
4164                 changingPkgName, changingPkg);
4165         // Make sure all dynamic permissions have been assigned to a package,
4166         // and make sure there are no dangling permissions.
4167         boolean permissionSourcePackageChanged = updatePermissionSourcePackage(changingPkgName,
4168                 changingPkg, callback);
4169 
4170         if (permissionTreesSourcePackageChanged | permissionSourcePackageChanged) {
4171             // Permission ownership has changed. This e.g. changes which packages can get signature
4172             // permissions
4173             Slog.i(TAG, "Permission ownership changed. Updating all permissions.");
4174             flags |= UPDATE_PERMISSIONS_ALL;
4175         }
4176 
4177         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "restorePermissionState");
4178         // Now update the permissions for all packages.
4179         if ((flags & UPDATE_PERMISSIONS_ALL) != 0) {
4180             final boolean replaceAll = ((flags & UPDATE_PERMISSIONS_REPLACE_ALL) != 0);
4181             mPackageManagerInt.forEachPackage((AndroidPackage pkg) -> {
4182                 if (pkg == changingPkg) {
4183                     return;
4184                 }
4185                 // Only replace for packages on requested volume
4186                 final String volumeUuid = getVolumeUuidForPackage(pkg);
4187                 final boolean replace = replaceAll && Objects.equals(replaceVolumeUuid, volumeUuid);
4188                 restorePermissionState(pkg, replace, changingPkgName, callback,
4189                         UserHandle.USER_ALL);
4190             });
4191         }
4192 
4193         if (changingPkg != null) {
4194             // Only replace for packages on requested volume
4195             final String volumeUuid = getVolumeUuidForPackage(changingPkg);
4196             final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_PKG) != 0)
4197                     && Objects.equals(replaceVolumeUuid, volumeUuid);
4198             restorePermissionState(changingPkg, replace, changingPkgName, callback,
4199                     UserHandle.USER_ALL);
4200         }
4201         Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
4202     }
4203 
4204     /**
4205      * Update which app declares a permission.
4206      *
4207      * <p>Possible parameter combinations
4208      * <table>
4209      *     <tr><th></th><th>packageName != null</th><th>packageName == null</th></tr>
4210      *     <tr><th>pkg != null</th><td>package is updated</td><td>invalid</td></tr>
4211      *     <tr><th>pkg == null</th><td>package is deleted</td><td>all packages are updated</td></tr>
4212      * </table>
4213      *
4214      * @param packageName The package that is updated, or {@code null} if all packages should be
4215      *                    updated
4216      * @param pkg The package that is updated, or {@code null} if all packages should be updated or
4217      *            package is deleted
4218      *
4219      * @return {@code true} if a permission source package might have changed
4220      */
4221     private boolean updatePermissionSourcePackage(@Nullable String packageName,
4222             @Nullable AndroidPackage pkg,
4223             final @Nullable PermissionCallback callback) {
4224         // Always need update if packageName is null
4225         if (packageName == null) {
4226             return true;
4227         }
4228 
4229         boolean changed = false;
4230         Set<Permission> needsUpdate = null;
4231         synchronized (mLock) {
4232             for (final Permission bp : mRegistry.getPermissions()) {
4233                 if (bp.isDynamic()) {
4234                     bp.updateDynamicPermission(mRegistry.getPermissionTrees());
4235                 }
4236                 if (!packageName.equals(bp.getPackageName())) {
4237                     // Not checking sourcePackageSetting because it can be null when
4238                     // the permission source package is the target package and the target package is
4239                     // being uninstalled,
4240                     continue;
4241                 }
4242                 // The target package is the source of the current permission
4243                 // Set to changed for either install or uninstall
4244                 changed = true;
4245                 if (needsUpdate == null) {
4246                     needsUpdate = new ArraySet<>();
4247                 }
4248                 needsUpdate.add(bp);
4249             }
4250         }
4251         if (needsUpdate != null) {
4252             for (final Permission bp : needsUpdate) {
4253                 // If the target package is being uninstalled, we need to revoke this permission
4254                 // From all other packages
4255                 if (pkg == null || !hasPermission(pkg, bp.getName())) {
4256                     Slog.i(TAG, "Removing permission " + bp.getName()
4257                             + " that used to be declared by " + bp.getPackageName());
4258                     if (bp.isRuntime()) {
4259                         final int[] userIds = mUserManagerInt.getUserIds();
4260                         final int numUserIds = userIds.length;
4261                         for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
4262                             final int userId = userIds[userIdNum];
4263                             mPackageManagerInt.forEachPackage((AndroidPackage p) ->
4264                                     revokePermissionFromPackageForUser(p.getPackageName(),
4265                                             bp.getName(), true, userId, callback));
4266                         }
4267                     } else {
4268                         mPackageManagerInt.forEachPackage(p -> {
4269                             final int[] userIds = mUserManagerInt.getUserIds();
4270                             synchronized (mLock) {
4271                                 for (final int userId : userIds) {
4272                                     final UidPermissionState uidState = getUidStateLocked(p,
4273                                             userId);
4274                                     if (uidState == null) {
4275                                         Slog.e(TAG, "Missing permissions state for "
4276                                                 + p.getPackageName() + " and user " + userId);
4277                                         continue;
4278                                     }
4279                                     uidState.removePermissionState(bp.getName());
4280                                 }
4281                             }
4282                         });
4283                     }
4284                     synchronized (mLock) {
4285                         mRegistry.removePermission(bp.getName());
4286                     }
4287                     continue;
4288                 }
4289                 final AndroidPackage sourcePkg =
4290                         mPackageManagerInt.getPackage(bp.getPackageName());
4291                 final PackageSetting sourcePs =
4292                         (PackageSetting) mPackageManagerInt.getPackageSetting(
4293                                 bp.getPackageName());
4294                 synchronized (mLock) {
4295                     if (sourcePkg != null && sourcePs != null) {
4296                         continue;
4297                     }
4298                     Slog.w(TAG, "Removing dangling permission: " + bp.getName()
4299                             + " from package " + bp.getPackageName());
4300                     mRegistry.removePermission(bp.getName());
4301                 }
4302             }
4303         }
4304         return changed;
4305     }
4306 
4307     /**
4308      * Revoke a runtime permission from a package for a given user ID.
4309      */
4310     private void revokePermissionFromPackageForUser(@NonNull String pName,
4311             @NonNull String permissionName, boolean overridePolicy, int userId,
4312             @Nullable PermissionCallback callback) {
4313         final ApplicationInfo appInfo =
4314                 mPackageManagerInt.getApplicationInfo(pName, 0,
4315                         Process.SYSTEM_UID, UserHandle.USER_SYSTEM);
4316         if (appInfo != null
4317                 && appInfo.targetSdkVersion < Build.VERSION_CODES.M) {
4318             return;
4319         }
4320 
4321         if (checkPermissionImpl(pName, permissionName, userId)
4322                 == PackageManager.PERMISSION_GRANTED) {
4323             try {
4324                 revokeRuntimePermissionInternal(
4325                         pName, permissionName,
4326                         overridePolicy,
4327                         Process.SYSTEM_UID,
4328                         userId,
4329                         null, callback);
4330             } catch (IllegalArgumentException e) {
4331                 Slog.e(TAG,
4332                         "Failed to revoke "
4333                                 + permissionName
4334                                 + " from "
4335                                 + pName,
4336                         e);
4337             }
4338         }
4339     }
4340     /**
4341      * Update which app owns a permission trees.
4342      *
4343      * <p>Possible parameter combinations
4344      * <table>
4345      *     <tr><th></th><th>packageName != null</th><th>packageName == null</th></tr>
4346      *     <tr><th>pkg != null</th><td>package is updated</td><td>invalid</td></tr>
4347      *     <tr><th>pkg == null</th><td>package is deleted</td><td>all packages are updated</td></tr>
4348      * </table>
4349      *
4350      * @param packageName The package that is updated, or {@code null} if all packages should be
4351      *                    updated
4352      * @param pkg The package that is updated, or {@code null} if all packages should be updated or
4353      *            package is deleted
4354      *
4355      * @return {@code true} if a permission tree ownership might have changed
4356      */
4357     private boolean updatePermissionTreeSourcePackage(@Nullable String packageName,
4358             @Nullable AndroidPackage pkg) {
4359         // Always need update if packageName is null
4360         if (packageName == null) {
4361             return true;
4362         }
4363         boolean changed = false;
4364 
4365         Set<Permission> needsUpdate = null;
4366         synchronized (mLock) {
4367             final Iterator<Permission> it = mRegistry.getPermissionTrees().iterator();
4368             while (it.hasNext()) {
4369                 final Permission bp = it.next();
4370                 if (!packageName.equals(bp.getPackageName())) {
4371                     // Not checking sourcePackageSetting because it can be null when
4372                     // the permission source package is the target package and the target package is
4373                     // being uninstalled,
4374                     continue;
4375                 }
4376                 // The target package is the source of the current permission tree
4377                 // Set to changed for either install or uninstall
4378                 changed = true;
4379                 if (pkg == null || !hasPermission(pkg, bp.getName())) {
4380                     Slog.i(TAG, "Removing permission tree " + bp.getName()
4381                             + " that used to be declared by " + bp.getPackageName());
4382                     it.remove();
4383                 }
4384                 if (needsUpdate == null) {
4385                     needsUpdate = new ArraySet<>();
4386                 }
4387                 needsUpdate.add(bp);
4388             }
4389         }
4390         if (needsUpdate != null) {
4391             for (final Permission bp : needsUpdate) {
4392                 final AndroidPackage sourcePkg =
4393                         mPackageManagerInt.getPackage(bp.getPackageName());
4394                 final PackageSetting sourcePs =
4395                         (PackageSetting) mPackageManagerInt.getPackageSetting(
4396                                 bp.getPackageName());
4397                 synchronized (mLock) {
4398                     if (sourcePkg != null && sourcePs != null) {
4399                         continue;
4400                     }
4401                     Slog.w(TAG, "Removing dangling permission tree: " + bp.getName()
4402                             + " from package " + bp.getPackageName());
4403                     mRegistry.removePermission(bp.getName());
4404                 }
4405             }
4406         }
4407         return changed;
4408     }
4409 
4410     private void enforceGrantRevokeRuntimePermissionPermissions(String message) {
4411         if (mContext.checkCallingOrSelfPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
4412                 != PackageManager.PERMISSION_GRANTED
4413             && mContext.checkCallingOrSelfPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
4414                 != PackageManager.PERMISSION_GRANTED) {
4415             throw new SecurityException(message + " requires "
4416                     + Manifest.permission.GRANT_RUNTIME_PERMISSIONS + " or "
4417                     + Manifest.permission.REVOKE_RUNTIME_PERMISSIONS);
4418         }
4419     }
4420 
4421     private void enforceGrantRevokeGetRuntimePermissionPermissions(@NonNull String message) {
4422         if (mContext.checkCallingOrSelfPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS)
4423                 != PackageManager.PERMISSION_GRANTED
4424             && mContext.checkCallingOrSelfPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
4425                 != PackageManager.PERMISSION_GRANTED
4426             && mContext.checkCallingOrSelfPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
4427                 != PackageManager.PERMISSION_GRANTED) {
4428             throw new SecurityException(message + " requires "
4429                     + Manifest.permission.GRANT_RUNTIME_PERMISSIONS + " or "
4430                     + Manifest.permission.REVOKE_RUNTIME_PERMISSIONS + " or "
4431                     + Manifest.permission.GET_RUNTIME_PERMISSIONS);
4432         }
4433     }
4434 
4435     /**
4436      * Enforces the request is from the system or an app that has INTERACT_ACROSS_USERS
4437      * or INTERACT_ACROSS_USERS_FULL permissions, if the {@code userId} is not for the caller.
4438      *
4439      * @param checkShell whether to prevent shell from access if there's a debugging restriction
4440      * @param message the message to log on security exception
4441      */
4442     private void enforceCrossUserPermission(int callingUid, @UserIdInt int userId,
4443             boolean requireFullPermission, boolean checkShell, @Nullable String message) {
4444         if (userId < 0) {
4445             throw new IllegalArgumentException("Invalid userId " + userId);
4446         }
4447         if (checkShell) {
4448             enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId);
4449         }
4450         final int callingUserId = UserHandle.getUserId(callingUid);
4451         if (checkCrossUserPermission(callingUid, callingUserId, userId, requireFullPermission)) {
4452             return;
4453         }
4454         String errorMessage = buildInvalidCrossUserPermissionMessage(
4455                 callingUid, userId, message, requireFullPermission);
4456         Slog.w(TAG, errorMessage);
4457         throw new SecurityException(errorMessage);
4458     }
4459 
4460     /**
4461      *  Enforces that if the caller is shell, it does not have the provided user restriction.
4462      */
4463     private void enforceShellRestriction(@NonNull String restriction, int callingUid,
4464             @UserIdInt int userId) {
4465         if (callingUid == Process.SHELL_UID) {
4466             if (userId >= 0 && mUserManagerInt.hasUserRestriction(restriction, userId)) {
4467                 throw new SecurityException("Shell does not have permission to access user "
4468                         + userId);
4469             } else if (userId < 0) {
4470                 Slog.e(LOG_TAG, "Unable to check shell permission for user "
4471                         + userId + "\n\t" + Debug.getCallers(3));
4472             }
4473         }
4474     }
4475 
4476     private boolean checkCrossUserPermission(int callingUid, @UserIdInt int callingUserId,
4477             @UserIdInt int userId, boolean requireFullPermission) {
4478         if (userId == callingUserId) {
4479             return true;
4480         }
4481         if (callingUid == Process.SYSTEM_UID || callingUid == Process.ROOT_UID) {
4482             return true;
4483         }
4484         if (requireFullPermission) {
4485             return checkCallingOrSelfPermission(
4486                     android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
4487         }
4488         return checkCallingOrSelfPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
4489                 || checkCallingOrSelfPermission(android.Manifest.permission.INTERACT_ACROSS_USERS);
4490     }
4491 
4492     private boolean checkCallingOrSelfPermission(String permission) {
4493         return mContext.checkCallingOrSelfPermission(permission)
4494                 == PackageManager.PERMISSION_GRANTED;
4495     }
4496 
4497     @NonNull
4498     private static String buildInvalidCrossUserPermissionMessage(int callingUid,
4499             @UserIdInt int userId, @Nullable String message, boolean requireFullPermission) {
4500         StringBuilder builder = new StringBuilder();
4501         if (message != null) {
4502             builder.append(message);
4503             builder.append(": ");
4504         }
4505         builder.append("UID ");
4506         builder.append(callingUid);
4507         builder.append(" requires ");
4508         builder.append(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
4509         if (!requireFullPermission) {
4510             builder.append(" or ");
4511             builder.append(android.Manifest.permission.INTERACT_ACROSS_USERS);
4512         }
4513         builder.append(" to access user ");
4514         builder.append(userId);
4515         builder.append(".");
4516         return builder.toString();
4517     }
4518 
4519     @GuardedBy("mLock")
4520     private int calculateCurrentPermissionFootprintLocked(@NonNull Permission permissionTree) {
4521         int size = 0;
4522         for (final Permission permission : mRegistry.getPermissions()) {
4523             size += permissionTree.calculateFootprint(permission);
4524         }
4525         return size;
4526     }
4527 
4528     @GuardedBy("mLock")
4529     private void enforcePermissionCapLocked(PermissionInfo info, Permission tree) {
4530         // We calculate the max size of permissions defined by this uid and throw
4531         // if that plus the size of 'info' would exceed our stated maximum.
4532         if (tree.getUid() != Process.SYSTEM_UID) {
4533             final int curTreeSize = calculateCurrentPermissionFootprintLocked(tree);
4534             if (curTreeSize + info.calculateFootprint() > MAX_PERMISSION_TREE_FOOTPRINT) {
4535                 throw new SecurityException("Permission tree size cap exceeded");
4536             }
4537         }
4538     }
4539 
4540     private void systemReady() {
4541         // Now that we've scanned all packages, and granted any default
4542         // permissions, ensure permissions are updated. Beware of dragons if you
4543         // try optimizing this.
4544         updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, false);
4545 
4546         final PermissionPolicyInternal permissionPolicyInternal = LocalServices.getService(
4547                 PermissionPolicyInternal.class);
4548         permissionPolicyInternal.setOnInitializedCallback(userId ->
4549                 // The SDK updated case is already handled when we run during the ctor.
4550                 updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, false)
4551         );
4552 
4553         mSystemReady = true;
4554 
4555         synchronized (mLock) {
4556             if (mPrivappPermissionsViolations != null) {
4557                 throw new IllegalStateException("Signature|privileged permissions not in "
4558                         + "privapp-permissions allowlist: " + mPrivappPermissionsViolations);
4559             }
4560         }
4561 
4562         mPermissionControllerManager = mContext.getSystemService(PermissionControllerManager.class);
4563         mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class);
4564     }
4565 
4566     private static String getVolumeUuidForPackage(AndroidPackage pkg) {
4567         if (pkg == null) {
4568             return StorageManager.UUID_PRIVATE_INTERNAL;
4569         }
4570         if (pkg.isExternalStorage()) {
4571             if (TextUtils.isEmpty(pkg.getVolumeUuid())) {
4572                 return StorageManager.UUID_PRIMARY_PHYSICAL;
4573             } else {
4574                 return pkg.getVolumeUuid();
4575             }
4576         } else {
4577             return StorageManager.UUID_PRIVATE_INTERNAL;
4578         }
4579     }
4580 
4581     private static boolean hasPermission(AndroidPackage pkg, String permName) {
4582         if (pkg.getPermissions().isEmpty()) {
4583             return false;
4584         }
4585 
4586         for (int i = pkg.getPermissions().size() - 1; i >= 0; i--) {
4587             if (pkg.getPermissions().get(i).getName().equals(permName)) {
4588                 return true;
4589             }
4590         }
4591         return false;
4592     }
4593 
4594     /**
4595      * Log that a permission request was granted/revoked.
4596      *
4597      * @param action the action performed
4598      * @param name name of the permission
4599      * @param packageName package permission is for
4600      */
4601     private void logPermission(int action, @NonNull String name, @NonNull String packageName) {
4602         final LogMaker log = new LogMaker(action);
4603         log.setPackageName(packageName);
4604         log.addTaggedData(MetricsEvent.FIELD_PERMISSION, name);
4605 
4606         mMetricsLogger.write(log);
4607     }
4608 
4609     @GuardedBy("mLock")
4610     @Nullable
4611     private UidPermissionState getUidStateLocked(@NonNull PackageSetting ps,
4612             @UserIdInt int userId) {
4613         return getUidStateLocked(ps.getAppId(), userId);
4614     }
4615 
4616     @GuardedBy("mLock")
4617     @Nullable
4618     private UidPermissionState getUidStateLocked(@NonNull AndroidPackage pkg,
4619             @UserIdInt int userId) {
4620         return getUidStateLocked(pkg.getUid(), userId);
4621     }
4622 
4623     @GuardedBy("mLock")
4624     @Nullable
4625     private UidPermissionState getUidStateLocked(@AppIdInt int appId, @UserIdInt int userId) {
4626         final UserPermissionState userState = mState.getUserState(userId);
4627         if (userState == null) {
4628             return null;
4629         }
4630         return userState.getUidState(appId);
4631     }
4632 
4633     private void removeUidStateAndResetPackageInstallPermissionsFixed(@AppIdInt int appId,
4634             @NonNull String packageName, @UserIdInt int userId) {
4635         synchronized (mLock) {
4636             final UserPermissionState userState = mState.getUserState(userId);
4637             if (userState == null) {
4638                 return;
4639             }
4640             userState.removeUidState(appId);
4641             userState.setInstallPermissionsFixed(packageName, false);
4642         }
4643     }
4644 
4645     private void readLegacyPermissionState() {
4646         final int[] userIds = getAllUserIds();
4647         mPackageManagerInt.forEachPackageSetting(ps -> {
4648             final int appId = ps.getAppId();
4649             final LegacyPermissionState legacyState = ps.getLegacyPermissionState();
4650 
4651             synchronized (mLock) {
4652                 for (final int userId : userIds) {
4653                     final UserPermissionState userState = mState.getOrCreateUserState(userId);
4654 
4655                     userState.setInstallPermissionsFixed(ps.name, ps.areInstallPermissionsFixed());
4656                     final UidPermissionState uidState = userState.getOrCreateUidState(appId);
4657                     uidState.reset();
4658                     uidState.setMissing(legacyState.isMissing(userId));
4659                     readLegacyPermissionStatesLocked(uidState,
4660                             legacyState.getPermissionStates(userId));
4661                 }
4662             }
4663         });
4664     }
4665 
4666     @GuardedBy("mLock")
4667     private void readLegacyPermissionStatesLocked(@NonNull UidPermissionState uidState,
4668             @NonNull Collection<LegacyPermissionState.PermissionState> permissionStates) {
4669         for (final LegacyPermissionState.PermissionState permissionState : permissionStates) {
4670             final String permissionName = permissionState.getName();
4671             final Permission permission = mRegistry.getPermission(permissionName);
4672             if (permission == null) {
4673                 Slog.w(TAG, "Unknown permission: " + permissionName);
4674                 continue;
4675             }
4676             uidState.putPermissionState(permission, permissionState.isGranted(),
4677                     permissionState.getFlags());
4678         }
4679     }
4680 
4681     private void writeLegacyPermissionState() {
4682         final int[] userIds;
4683         synchronized (mLock) {
4684             userIds = mState.getUserIds();
4685         }
4686         mPackageManagerInt.forEachPackageSetting(ps -> {
4687             ps.setInstallPermissionsFixed(false);
4688             final LegacyPermissionState legacyState = ps.getLegacyPermissionState();
4689             legacyState.reset();
4690             final int appId = ps.getAppId();
4691 
4692             synchronized (mLock) {
4693                 for (final int userId : userIds) {
4694                     final UserPermissionState userState = mState.getUserState(userId);
4695                     if (userState == null) {
4696                         Slog.e(TAG, "Missing user state for " + userId);
4697                         continue;
4698                     }
4699 
4700                     if (userState.areInstallPermissionsFixed(ps.name)) {
4701                         ps.setInstallPermissionsFixed(true);
4702                     }
4703 
4704                     final UidPermissionState uidState = userState.getUidState(appId);
4705                     if (uidState == null) {
4706                         Slog.e(TAG, "Missing permission state for " + ps.name + " and user "
4707                                 + userId);
4708                         continue;
4709                     }
4710 
4711                     legacyState.setMissing(uidState.isMissing(), userId);
4712                     final List<PermissionState> permissionStates = uidState.getPermissionStates();
4713                     final int permissionStatesSize = permissionStates.size();
4714                     for (int i = 0; i < permissionStatesSize; i++) {
4715                         final PermissionState permissionState = permissionStates.get(i);
4716 
4717                         final LegacyPermissionState.PermissionState legacyPermissionState =
4718                                 new LegacyPermissionState.PermissionState(permissionState.getName(),
4719                                         permissionState.getPermission().isRuntime(),
4720                                         permissionState.isGranted(), permissionState.getFlags());
4721                         legacyState.putPermissionState(legacyPermissionState, userId);
4722                     }
4723                 }
4724             }
4725         });
4726     }
4727 
4728     private void readLegacyPermissions(@NonNull LegacyPermissionSettings legacyPermissionSettings) {
4729         for (int readPermissionOrPermissionTree = 0; readPermissionOrPermissionTree < 2;
4730                 readPermissionOrPermissionTree++) {
4731             final List<LegacyPermission> legacyPermissions = readPermissionOrPermissionTree == 0
4732                     ? legacyPermissionSettings.getPermissions()
4733                     : legacyPermissionSettings.getPermissionTrees();
4734             synchronized (mLock) {
4735                 final int legacyPermissionsSize = legacyPermissions.size();
4736                 for (int i = 0; i < legacyPermissionsSize; i++) {
4737                     final LegacyPermission legacyPermission = legacyPermissions.get(i);
4738                     final Permission permission = new Permission(
4739                             legacyPermission.getPermissionInfo(), legacyPermission.getType());
4740                     if (readPermissionOrPermissionTree == 0) {
4741                         // Config permissions are currently read in PermissionManagerService
4742                         // constructor. The old behavior was to add other attributes to the config
4743                         // permission in LegacyPermission.read(), so equivalently we can add the
4744                         // GIDs to the new permissions here, since config permissions created in
4745                         // PermissionManagerService constructor get only their names and GIDs there.
4746                         final Permission configPermission = mRegistry.getPermission(
4747                                 permission.getName());
4748                         if (configPermission != null
4749                                 && configPermission.getType() == Permission.TYPE_CONFIG) {
4750                             permission.setGids(configPermission.getRawGids(),
4751                                     configPermission.areGidsPerUser());
4752                         }
4753                         mRegistry.addPermission(permission);
4754                     } else {
4755                         mRegistry.addPermissionTree(permission);
4756                     }
4757                 }
4758             }
4759         }
4760     }
4761 
4762     private void writeLegacyPermissions(
4763             @NonNull LegacyPermissionSettings legacyPermissionSettings) {
4764         for (int writePermissionOrPermissionTree = 0; writePermissionOrPermissionTree < 2;
4765                 writePermissionOrPermissionTree++) {
4766             final List<LegacyPermission> legacyPermissions = new ArrayList<>();
4767             synchronized (mLock) {
4768                 final Collection<Permission> permissions = writePermissionOrPermissionTree == 0
4769                         ? mRegistry.getPermissions() : mRegistry.getPermissionTrees();
4770                 for (final Permission permission : permissions) {
4771                     // We don't need to provide UID and GIDs, which are only retrieved when dumping.
4772                     final LegacyPermission legacyPermission = new LegacyPermission(
4773                             permission.getPermissionInfo(), permission.getType(), 0,
4774                             EmptyArray.INT);
4775                     legacyPermissions.add(legacyPermission);
4776                 }
4777             }
4778             if (writePermissionOrPermissionTree == 0) {
4779                 legacyPermissionSettings.replacePermissions(legacyPermissions);
4780             } else {
4781                 legacyPermissionSettings.replacePermissionTrees(legacyPermissions);
4782             }
4783         }
4784     }
4785 
4786     private void onPackageAddedInternal(@NonNull AndroidPackage pkg, boolean isInstantApp,
4787             @Nullable AndroidPackage oldPkg) {
4788         if (!pkg.getAdoptPermissions().isEmpty()) {
4789             // This package wants to adopt ownership of permissions from
4790             // another package.
4791             for (int i = pkg.getAdoptPermissions().size() - 1; i >= 0; i--) {
4792                 final String origName = pkg.getAdoptPermissions().get(i);
4793                 if (canAdoptPermissionsInternal(origName, pkg)) {
4794                     Slog.i(TAG, "Adopting permissions from " + origName + " to "
4795                             + pkg.getPackageName());
4796                     synchronized (mLock) {
4797                         mRegistry.transferPermissions(origName, pkg.getPackageName());
4798                     }
4799                 }
4800             }
4801         }
4802 
4803         // Don't allow ephemeral applications to define new permissions groups.
4804         if (isInstantApp) {
4805             Slog.w(TAG, "Permission groups from package " + pkg.getPackageName()
4806                     + " ignored: instant apps cannot define new permission groups.");
4807         } else {
4808             addAllPermissionGroupsInternal(pkg);
4809         }
4810 
4811         // If a permission has had its defining app changed, or it has had its protection
4812         // upgraded, we need to revoke apps that hold it
4813         final List<String> permissionsWithChangedDefinition;
4814         // Don't allow ephemeral applications to define new permissions.
4815         if (isInstantApp) {
4816             permissionsWithChangedDefinition = null;
4817             Slog.w(TAG, "Permissions from package " + pkg.getPackageName()
4818                     + " ignored: instant apps cannot define new permissions.");
4819         } else {
4820             permissionsWithChangedDefinition = addAllPermissionsInternal(pkg);
4821         }
4822 
4823         boolean hasOldPkg = oldPkg != null;
4824         boolean hasPermissionDefinitionChanges =
4825                 !CollectionUtils.isEmpty(permissionsWithChangedDefinition);
4826         if (hasOldPkg || hasPermissionDefinitionChanges) {
4827             // We need to call revokeRuntimePermissionsIfGroupChanged async as permission
4828             // revoke callbacks from this method might need to kill apps which need the
4829             // mPackages lock on a different thread. This would dead lock.
4830             AsyncTask.execute(() -> {
4831                 if (hasOldPkg) {
4832                     revokeRuntimePermissionsIfGroupChangedInternal(pkg, oldPkg);
4833                     revokeStoragePermissionsIfScopeExpandedInternal(pkg, oldPkg);
4834                 }
4835                 if (hasPermissionDefinitionChanges) {
4836                     revokeRuntimePermissionsIfPermissionDefinitionChangedInternal(
4837                             permissionsWithChangedDefinition);
4838                 }
4839             });
4840         }
4841     }
4842 
4843     private boolean canAdoptPermissionsInternal(@NonNull String oldPackageName,
4844             @NonNull AndroidPackage newPkg) {
4845         final PackageSetting oldPs = mPackageManagerInt.getPackageSetting(oldPackageName);
4846         if (oldPs == null) {
4847             return false;
4848         }
4849         if (!oldPs.isSystem()) {
4850             Slog.w(TAG, "Unable to update from " + oldPs.name
4851                     + " to " + newPkg.getPackageName()
4852                     + ": old package not in system partition");
4853             return false;
4854         }
4855         if (mPackageManagerInt.getPackage(oldPs.name) != null) {
4856             Slog.w(TAG, "Unable to update from " + oldPs.name
4857                     + " to " + newPkg.getPackageName()
4858                     + ": old package still exists");
4859             return false;
4860         }
4861         return true;
4862     }
4863 
4864     private void onPackageInstalledInternal(@NonNull AndroidPackage pkg,
4865             @NonNull PermissionManagerServiceInternal.PackageInstalledParams params,
4866             @UserIdInt int[] userIds) {
4867         updatePermissions(pkg.getPackageName(), pkg);
4868         for (final int userId : userIds) {
4869             addAllowlistedRestrictedPermissionsInternal(pkg,
4870                     params.getAllowlistedRestrictedPermissions(),
4871                     FLAG_PERMISSION_WHITELIST_INSTALLER, userId);
4872             final int autoRevokePermissionsMode = params.getAutoRevokePermissionsMode();
4873             if (autoRevokePermissionsMode == AppOpsManager.MODE_ALLOWED
4874                     || autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED) {
4875                 setAutoRevokeExemptedInternal(pkg,
4876                         autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED, userId);
4877             }
4878             grantRequestedRuntimePermissionsInternal(pkg, params.getGrantedPermissions(), userId);
4879         }
4880     }
4881 
4882     private void addAllowlistedRestrictedPermissionsInternal(@NonNull AndroidPackage pkg,
4883             @NonNull List<String> allowlistedRestrictedPermissions,
4884             @PermissionWhitelistFlags int flags, @UserIdInt int userId) {
4885         List<String> permissions = getAllowlistedRestrictedPermissionsInternal(pkg, flags, userId);
4886         if (permissions != null) {
4887             ArraySet<String> permissionSet = new ArraySet<>(permissions);
4888             permissionSet.addAll(allowlistedRestrictedPermissions);
4889             permissions = new ArrayList<>(permissionSet);
4890         } else {
4891             permissions = allowlistedRestrictedPermissions;
4892         }
4893         setAllowlistedRestrictedPermissionsInternal(pkg, permissions, flags, userId);
4894     }
4895 
4896     private void onPackageRemovedInternal(@NonNull AndroidPackage pkg) {
4897         removeAllPermissionsInternal(pkg);
4898     }
4899 
4900     private void onPackageUninstalledInternal(@NonNull String packageName, int appId,
4901             @Nullable AndroidPackage pkg, @NonNull List<AndroidPackage> sharedUserPkgs,
4902             @UserIdInt int[] userIds) {
4903         // TODO: Move these checks to check PackageState to be more reliable.
4904         // System packages should always have an available APK.
4905         if (pkg != null && pkg.isSystem()
4906                 // We may be fully removing invalid system packages during boot, and in that case we
4907                 // do want to remove their permission state. So make sure that the package is only
4908                 // being marked as uninstalled instead of fully removed.
4909                 && mPackageManagerInt.getPackage(packageName) != null) {
4910             // If we are only marking a system package as uninstalled, we need to keep its
4911             // pregranted permission state so that it still works once it gets reinstalled, thus
4912             // only reset the user modifications to its permission state.
4913             for (final int userId : userIds) {
4914                 resetRuntimePermissionsInternal(pkg, userId);
4915             }
4916             return;
4917         }
4918         updatePermissions(packageName, null);
4919         for (final int userId : userIds) {
4920             if (sharedUserPkgs.isEmpty()) {
4921                 removeUidStateAndResetPackageInstallPermissionsFixed(appId, packageName, userId);
4922             } else {
4923                 // Remove permissions associated with package. Since runtime
4924                 // permissions are per user we have to kill the removed package
4925                 // or packages running under the shared user of the removed
4926                 // package if revoking the permissions requested only by the removed
4927                 // package is successful and this causes a change in gids.
4928                 final int userIdToKill = revokeSharedUserPermissionsForDeletedPackageInternal(pkg,
4929                         sharedUserPkgs, userId);
4930                 final boolean shouldKill = userIdToKill != UserHandle.USER_NULL;
4931                 // If gids changed, kill all affected packages.
4932                 if (shouldKill) {
4933                     mHandler.post(() -> {
4934                         // This has to happen with no lock held.
4935                         killUid(appId, UserHandle.USER_ALL, KILL_APP_REASON_GIDS_CHANGED);
4936                     });
4937                 }
4938             }
4939         }
4940     }
4941 
4942     @NonNull
4943     private List<LegacyPermission> getLegacyPermissions() {
4944         synchronized (mLock) {
4945             final List<LegacyPermission> legacyPermissions = new ArrayList<>();
4946             for (final Permission permission : mRegistry.getPermissions()) {
4947                 final LegacyPermission legacyPermission = new LegacyPermission(
4948                         permission.getPermissionInfo(), permission.getType(), permission.getUid(),
4949                         permission.getRawGids());
4950                 legacyPermissions.add(legacyPermission);
4951             }
4952             return legacyPermissions;
4953         }
4954     }
4955 
4956     @NonNull
4957     private Map<String, Set<String>> getAllAppOpPermissionPackages() {
4958         synchronized (mLock) {
4959             final ArrayMap<String, ArraySet<String>> appOpPermissionPackages =
4960                     mRegistry.getAllAppOpPermissionPackages();
4961             final Map<String, Set<String>> deepClone = new ArrayMap<>();
4962             final int appOpPermissionPackagesSize = appOpPermissionPackages.size();
4963             for (int i = 0; i < appOpPermissionPackagesSize; i++) {
4964                 final String appOpPermission = appOpPermissionPackages.keyAt(i);
4965                 final ArraySet<String> packageNames = appOpPermissionPackages.valueAt(i);
4966                 deepClone.put(appOpPermission, new ArraySet<>(packageNames));
4967             }
4968             return deepClone;
4969         }
4970     }
4971 
4972     @NonNull
4973     private LegacyPermissionState getLegacyPermissionState(@AppIdInt int appId) {
4974         final LegacyPermissionState legacyState = new LegacyPermissionState();
4975         synchronized (mLock) {
4976             final int[] userIds = mState.getUserIds();
4977             for (final int userId : userIds) {
4978                 final UidPermissionState uidState = getUidStateLocked(appId, userId);
4979                 if (uidState == null) {
4980                     Slog.e(TAG, "Missing permissions state for app ID " + appId + " and user ID "
4981                             + userId);
4982                     continue;
4983                 }
4984 
4985                 final List<PermissionState> permissionStates = uidState.getPermissionStates();
4986                 final int permissionStatesSize = permissionStates.size();
4987                 for (int i = 0; i < permissionStatesSize; i++) {
4988                     final PermissionState permissionState = permissionStates.get(i);
4989 
4990                     final LegacyPermissionState.PermissionState legacyPermissionState =
4991                             new LegacyPermissionState.PermissionState(permissionState.getName(),
4992                                     permissionState.getPermission().isRuntime(),
4993                                     permissionState.isGranted(), permissionState.getFlags());
4994                     legacyState.putPermissionState(legacyPermissionState, userId);
4995                 }
4996             }
4997         }
4998         return legacyState;
4999     }
5000 
5001     @NonNull
5002     private int[] getGidsForUid(int uid) {
5003         final int appId = UserHandle.getAppId(uid);
5004         final int userId = UserHandle.getUserId(uid);
5005         synchronized (mLock) {
5006             final UidPermissionState uidState = getUidStateLocked(appId, userId);
5007             if (uidState == null) {
5008                 Slog.e(TAG, "Missing permissions state for app ID " + appId + " and user ID "
5009                         + userId);
5010                 return EMPTY_INT_ARRAY;
5011             }
5012             return uidState.computeGids(mGlobalGids, userId);
5013         }
5014     }
5015 
5016     private class PermissionManagerServiceInternalImpl implements PermissionManagerServiceInternal {
5017         @Override
5018         public int checkPermission(@NonNull String packageName, @NonNull String permissionName,
5019                 @UserIdInt int userId) {
5020             return PermissionManagerService.this.checkPermission(packageName, permissionName,
5021                     userId);
5022         }
5023 
5024         @Override
5025         public int checkUidPermission(int uid, @NonNull String permissionName) {
5026             return PermissionManagerService.this.checkUidPermission(uid, permissionName);
5027         }
5028 
5029         @Override
5030         public void onSystemReady() {
5031             PermissionManagerService.this.systemReady();
5032         }
5033 
5034         @Override
5035         public boolean isPermissionsReviewRequired(@NonNull String packageName,
5036                 @UserIdInt int userId) {
5037             Objects.requireNonNull(packageName, "packageName");
5038             // TODO(b/173235285): Some caller may pass USER_ALL as userId.
5039             //Preconditions.checkArgumentNonnegative(userId, "userId");
5040             return isPermissionsReviewRequiredInternal(packageName, userId);
5041         }
5042 
5043         @Override
5044         public void readLegacyPermissionStateTEMP() {
5045             PermissionManagerService.this.readLegacyPermissionState();
5046         }
5047         @Override
5048         public void writeLegacyPermissionStateTEMP() {
5049             PermissionManagerService.this.writeLegacyPermissionState();
5050         }
5051         @Override
5052         public void onUserRemoved(@UserIdInt int userId) {
5053             Preconditions.checkArgumentNonNegative(userId, "userId");
5054             PermissionManagerService.this.onUserRemoved(userId);
5055         }
5056         @NonNull
5057         @Override
5058         public Set<String> getGrantedPermissions(@NonNull String packageName,
5059                 @UserIdInt int userId) {
5060             Objects.requireNonNull(packageName, "packageName");
5061             Preconditions.checkArgumentNonNegative(userId, "userId");
5062             return getGrantedPermissionsInternal(packageName, userId);
5063         }
5064         @NonNull
5065         @Override
5066         public int[] getPermissionGids(@NonNull String permissionName, @UserIdInt int userId) {
5067             Objects.requireNonNull(permissionName, "permissionName");
5068             Preconditions.checkArgumentNonNegative(userId, "userId");
5069             return getPermissionGidsInternal(permissionName, userId);
5070         }
5071         @NonNull
5072         @Override
5073         public String[] getAppOpPermissionPackages(@NonNull String permissionName) {
5074             Objects.requireNonNull(permissionName, "permissionName");
5075             return PermissionManagerService.this.getAppOpPermissionPackagesInternal(permissionName);
5076         }
5077         @Override
5078         public void onStorageVolumeMounted(@Nullable String volumeUuid, boolean fingerprintChanged) {
5079             updateAllPermissions(volumeUuid, fingerprintChanged);
5080         }
5081         @Override
5082         public void resetRuntimePermissions(@NonNull AndroidPackage pkg, @UserIdInt int userId) {
5083             Objects.requireNonNull(pkg, "pkg");
5084             Preconditions.checkArgumentNonNegative(userId, "userId");
5085             resetRuntimePermissionsInternal(pkg, userId);
5086         }
5087 
5088         @Override
5089         public Permission getPermissionTEMP(String permName) {
5090             synchronized (mLock) {
5091                 return mRegistry.getPermission(permName);
5092             }
5093         }
5094 
5095         @Override
5096         public @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtection(
5097                 @PermissionInfo.Protection int protection) {
5098             ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
5099 
5100             synchronized (mLock) {
5101                 for (final Permission permission : mRegistry.getPermissions()) {
5102                     if (permission.getProtection() == protection) {
5103                         matchingPermissions.add(permission.generatePermissionInfo(0));
5104                     }
5105                 }
5106             }
5107 
5108             return matchingPermissions;
5109         }
5110 
5111         @Override
5112         public @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtectionFlags(
5113                 @PermissionInfo.ProtectionFlags int protectionFlags) {
5114             ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
5115 
5116             synchronized (mLock) {
5117                 for (final Permission permission : mRegistry.getPermissions()) {
5118                     if ((permission.getProtectionFlags() & protectionFlags) == protectionFlags) {
5119                         matchingPermissions.add(permission.generatePermissionInfo(0));
5120                     }
5121                 }
5122             }
5123 
5124             return matchingPermissions;
5125         }
5126 
5127         @Nullable
5128         @Override
5129         public byte[] backupRuntimePermissions(@UserIdInt int userId) {
5130             Preconditions.checkArgumentNonNegative(userId, "userId");
5131             return PermissionManagerService.this.backupRuntimePermissions(userId);
5132         }
5133 
5134         @Override
5135         public void restoreRuntimePermissions(@NonNull byte[] backup, @UserIdInt int userId) {
5136             Objects.requireNonNull(backup, "backup");
5137             Preconditions.checkArgumentNonNegative(userId, "userId");
5138             PermissionManagerService.this.restoreRuntimePermissions(backup, userId);
5139         }
5140 
5141         @Override
5142         public void restoreDelayedRuntimePermissions(@NonNull String packageName,
5143                 @UserIdInt int userId) {
5144             Objects.requireNonNull(packageName, "packageName");
5145             Preconditions.checkArgumentNonNegative(userId, "userId");
5146             PermissionManagerService.this.restoreDelayedRuntimePermissions(packageName, userId);
5147         }
5148 
5149         @Override
5150         public void addOnRuntimePermissionStateChangedListener(
5151                 OnRuntimePermissionStateChangedListener listener) {
5152             PermissionManagerService.this.addOnRuntimePermissionStateChangedListener(
5153                     listener);
5154         }
5155 
5156         @Override
5157         public void removeOnRuntimePermissionStateChangedListener(
5158                 OnRuntimePermissionStateChangedListener listener) {
5159             PermissionManagerService.this.removeOnRuntimePermissionStateChangedListener(
5160                     listener);
5161         }
5162 
5163         @Override
5164         public void startShellPermissionIdentityDelegation(int uid, @NonNull String packageName,
5165                 @Nullable List<String> permissionNames) {
5166             Objects.requireNonNull(packageName, "packageName");
5167             startShellPermissionIdentityDelegationInternal(uid, packageName, permissionNames);
5168         }
5169 
5170         @Override
5171         public void stopShellPermissionIdentityDelegation() {
5172             stopShellPermissionIdentityDelegationInternal();
5173         }
5174 
5175         @Override
5176         @NonNull
5177         public List<String> getDelegatedShellPermissions() {
5178             return getDelegatedShellPermissionsInternal();
5179         }
5180 
5181         @Override
5182         public void onUserCreated(@UserIdInt int userId) {
5183             Preconditions.checkArgumentNonNegative(userId, "userId");
5184             // NOTE: This adds UPDATE_PERMISSIONS_REPLACE_PKG
5185             updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, true);
5186         }
5187 
5188         @Override
5189         public void readLegacyPermissionsTEMP(
5190                 @NonNull LegacyPermissionSettings legacyPermissionSettings) {
5191             PermissionManagerService.this.readLegacyPermissions(legacyPermissionSettings);
5192         }
5193 
5194         @Override
5195         public void writeLegacyPermissionsTEMP(
5196                 @NonNull LegacyPermissionSettings legacyPermissionSettings) {
5197             PermissionManagerService.this.writeLegacyPermissions(legacyPermissionSettings);
5198         }
5199 
5200         @Override
5201         public void onPackageAdded(@NonNull AndroidPackage pkg, boolean isInstantApp,
5202                 @Nullable AndroidPackage oldPkg) {
5203             Objects.requireNonNull(pkg);
5204             onPackageAddedInternal(pkg, isInstantApp, oldPkg);
5205         }
5206 
5207         @Override
5208         public void onPackageInstalled(@NonNull AndroidPackage pkg,
5209                 @NonNull PackageInstalledParams params, @UserIdInt int userId) {
5210             Objects.requireNonNull(pkg, "pkg");
5211             Objects.requireNonNull(params, "params");
5212             Preconditions.checkArgument(userId >= UserHandle.USER_SYSTEM
5213                     || userId == UserHandle.USER_ALL, "userId");
5214             final int[] userIds = userId == UserHandle.USER_ALL ? getAllUserIds()
5215                     : new int[] { userId };
5216             onPackageInstalledInternal(pkg, params, userIds);
5217         }
5218 
5219         @Override
5220         public void onPackageRemoved(@NonNull AndroidPackage pkg) {
5221             Objects.requireNonNull(pkg);
5222             onPackageRemovedInternal(pkg);
5223         }
5224 
5225         @Override
5226         public void onPackageUninstalled(@NonNull String packageName, int appId,
5227                 @Nullable AndroidPackage pkg, @NonNull List<AndroidPackage> sharedUserPkgs,
5228                 @UserIdInt int userId) {
5229             Objects.requireNonNull(packageName, "packageName");
5230             Objects.requireNonNull(sharedUserPkgs, "sharedUserPkgs");
5231             Preconditions.checkArgument(userId >= UserHandle.USER_SYSTEM
5232                     || userId == UserHandle.USER_ALL, "userId");
5233             final int[] userIds = userId == UserHandle.USER_ALL ? getAllUserIds()
5234                     : new int[] { userId };
5235             onPackageUninstalledInternal(packageName, appId, pkg, sharedUserPkgs, userIds);
5236         }
5237 
5238         @NonNull
5239         @Override
5240         public List<LegacyPermission> getLegacyPermissions() {
5241             return PermissionManagerService.this.getLegacyPermissions();
5242         }
5243 
5244         @NonNull
5245         @Override
5246         public Map<String, Set<String>> getAllAppOpPermissionPackages() {
5247             return PermissionManagerService.this.getAllAppOpPermissionPackages();
5248         }
5249 
5250         @NonNull
5251         @Override
5252         public LegacyPermissionState getLegacyPermissionState(@AppIdInt int appId) {
5253             return PermissionManagerService.this.getLegacyPermissionState(appId);
5254         }
5255 
5256         @NonNull
5257         @Override
5258         public int[] getGidsForUid(int uid) {
5259             return PermissionManagerService.this.getGidsForUid(uid);
5260         }
5261 
5262         @Override
5263         public void setHotwordDetectionServiceProvider(HotwordDetectionServiceProvider provider) {
5264             mHotwordDetectionServiceProvider = provider;
5265         }
5266 
5267         @Override
5268         public HotwordDetectionServiceProvider getHotwordDetectionServiceProvider() {
5269             return mHotwordDetectionServiceProvider;
5270         }
5271     }
5272 
5273     /**
5274      * Callbacks invoked when interesting actions have been taken on a permission.
5275      * <p>
5276      * NOTE: The current arguments are merely to support the existing use cases. This
5277      * needs to be properly thought out with appropriate arguments for each of the
5278      * callback methods.
5279      */
5280     private static class PermissionCallback {
5281         public void onGidsChanged(@AppIdInt int appId, @UserIdInt int userId) {}
5282         public void onPermissionChanged() {}
5283         public void onPermissionGranted(int uid, @UserIdInt int userId) {}
5284         public void onInstallPermissionGranted() {}
5285         public void onPermissionRevoked(int uid, @UserIdInt int userId, String reason) {}
5286         public void onInstallPermissionRevoked() {}
5287         public void onPermissionUpdated(@UserIdInt int[] updatedUserIds, boolean sync) {}
5288         public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds, boolean sync,
5289                 int uid) {
5290             onPermissionUpdated(updatedUserIds, sync);
5291         }
5292         public void onPermissionRemoved() {}
5293         public void onInstallPermissionUpdated() {}
5294         public void onInstallPermissionUpdatedNotifyListener(int uid) {
5295             onInstallPermissionUpdated();
5296         }
5297     }
5298 
5299     private static final class OnPermissionChangeListeners extends Handler {
5300         private static final int MSG_ON_PERMISSIONS_CHANGED = 1;
5301 
5302         private final RemoteCallbackList<IOnPermissionsChangeListener> mPermissionListeners =
5303                 new RemoteCallbackList<>();
5304 
5305         OnPermissionChangeListeners(Looper looper) {
5306             super(looper);
5307         }
5308 
5309         @Override
5310         public void handleMessage(Message msg) {
5311             switch (msg.what) {
5312                 case MSG_ON_PERMISSIONS_CHANGED: {
5313                     final int uid = msg.arg1;
5314                     handleOnPermissionsChanged(uid);
5315                 } break;
5316             }
5317         }
5318 
5319         public void addListener(IOnPermissionsChangeListener listener) {
5320             mPermissionListeners.register(listener);
5321         }
5322 
5323         public void removeListener(IOnPermissionsChangeListener listener) {
5324             mPermissionListeners.unregister(listener);
5325         }
5326 
5327         public void onPermissionsChanged(int uid) {
5328             if (mPermissionListeners.getRegisteredCallbackCount() > 0) {
5329                 obtainMessage(MSG_ON_PERMISSIONS_CHANGED, uid, 0).sendToTarget();
5330             }
5331         }
5332 
5333         private void handleOnPermissionsChanged(int uid) {
5334             final int count = mPermissionListeners.beginBroadcast();
5335             try {
5336                 for (int i = 0; i < count; i++) {
5337                     IOnPermissionsChangeListener callback = mPermissionListeners
5338                             .getBroadcastItem(i);
5339                     try {
5340                         callback.onPermissionsChanged(uid);
5341                     } catch (RemoteException e) {
5342                         Log.e(TAG, "Permission listener is dead", e);
5343                     }
5344                 }
5345             } finally {
5346                 mPermissionListeners.finishBroadcast();
5347             }
5348         }
5349     }
5350 
5351     /**
5352      * Interface to intercept permission checks and optionally pass through to the original
5353      * implementation.
5354      */
5355     private interface CheckPermissionDelegate {
5356         /**
5357          * Get the UID whose permission checks is being delegated.
5358          *
5359          * @return the UID
5360          */
5361         int getDelegatedUid();
5362 
5363         /**
5364          * Check whether the given package has been granted the specified permission.
5365          *
5366          * @param packageName the name of the package to be checked
5367          * @param permissionName the name of the permission to be checked
5368          * @param userId the user ID
5369          * @param superImpl the original implementation that can be delegated to
5370          * @return {@link android.content.pm.PackageManager#PERMISSION_GRANTED} if the package has
5371          * the permission, or {@link android.content.pm.PackageManager#PERMISSION_DENIED} otherwise
5372          *
5373          * @see android.content.pm.PackageManager#checkPermission(String, String)
5374          */
5375         int checkPermission(@NonNull String packageName, @NonNull String permissionName,
5376                 @UserIdInt int userId,
5377                 @NonNull TriFunction<String, String, Integer, Integer> superImpl);
5378 
5379         /**
5380          * Check whether the given UID has been granted the specified permission.
5381          *
5382          * @param uid the UID to be checked
5383          * @param permissionName the name of the permission to be checked
5384          * @param superImpl the original implementation that can be delegated to
5385          * @return {@link android.content.pm.PackageManager#PERMISSION_GRANTED} if the package has
5386          * the permission, or {@link android.content.pm.PackageManager#PERMISSION_DENIED} otherwise
5387          */
5388         int checkUidPermission(int uid, @NonNull String permissionName,
5389                 BiFunction<Integer, String, Integer> superImpl);
5390 
5391         /**
5392          * @return list of delegated permissions
5393          */
5394         List<String> getDelegatedPermissionNames();
5395     }
5396 
5397     private class ShellDelegate implements CheckPermissionDelegate {
5398         private final int mDelegatedUid;
5399         @NonNull
5400         private final String mDelegatedPackageName;
5401         @Nullable
5402         private final List<String> mDelegatedPermissionNames;
5403 
5404         public ShellDelegate(int delegatedUid, @NonNull String delegatedPackageName,
5405                 @Nullable List<String> delegatedPermissionNames) {
5406             mDelegatedUid = delegatedUid;
5407             mDelegatedPackageName = delegatedPackageName;
5408             mDelegatedPermissionNames = delegatedPermissionNames;
5409         }
5410 
5411         @Override
5412         public int getDelegatedUid() {
5413             return mDelegatedUid;
5414         }
5415 
5416         @Override
5417         public int checkPermission(@NonNull String packageName, @NonNull String permissionName,
5418                 int userId, @NonNull TriFunction<String, String, Integer, Integer> superImpl) {
5419             if (mDelegatedPackageName.equals(packageName)
5420                     && isDelegatedPermission(permissionName)) {
5421                 final long identity = Binder.clearCallingIdentity();
5422                 try {
5423                     return superImpl.apply("com.android.shell", permissionName, userId);
5424                 } finally {
5425                     Binder.restoreCallingIdentity(identity);
5426                 }
5427             }
5428             return superImpl.apply(packageName, permissionName, userId);
5429         }
5430 
5431         @Override
5432         public int checkUidPermission(int uid, @NonNull String permissionName,
5433                 @NonNull BiFunction<Integer, String, Integer> superImpl) {
5434             if (uid == mDelegatedUid && isDelegatedPermission(permissionName)) {
5435                 final long identity = Binder.clearCallingIdentity();
5436                 try {
5437                     return superImpl.apply(Process.SHELL_UID, permissionName);
5438                 } finally {
5439                     Binder.restoreCallingIdentity(identity);
5440                 }
5441             }
5442             return superImpl.apply(uid, permissionName);
5443         }
5444 
5445         @Override
5446         public List<String> getDelegatedPermissionNames() {
5447             return mDelegatedPermissionNames == null
5448                     ? null
5449                     : new ArrayList<>(mDelegatedPermissionNames);
5450         }
5451 
5452         private boolean isDelegatedPermission(@NonNull String permissionName) {
5453             // null permissions means all permissions are targeted
5454             return mDelegatedPermissionNames == null
5455                     || mDelegatedPermissionNames.contains(permissionName);
5456         }
5457     }
5458 
5459     private static final class AttributionSourceRegistry {
5460         private final Object mLock = new Object();
5461 
5462         private final Context mContext;
5463 
5464         AttributionSourceRegistry(@NonNull Context context) {
5465             mContext = context;
5466         }
5467 
5468         private final WeakHashMap<IBinder, AttributionSource> mAttributions = new WeakHashMap<>();
5469 
5470         public void registerAttributionSource(@NonNull AttributionSource source) {
5471             //   Here we keep track of attribution sources that were created by an app
5472             // from an attribution chain that called into the app and the apps's
5473             // own attribution source. An app can register an attribution chain up
5474             // to itself inclusive if and only if it is adding a node for itself which
5475             // optionally points to an attribution chain that was created by each
5476             // preceding app recursively up to the beginning of the chain.
5477             //   The only special case is when the first app in the attribution chain
5478             // creates a source that points to another app (not a chain of apps). We
5479             // allow this even if the source the app points to is not registered since
5480             // in app ops we allow every app to blame every other app (untrusted if not
5481             // holding a special permission).
5482             //  This technique ensures that a bad actor in the middle of the attribution
5483             // chain can neither prepend nor append an invalid attribution sequence, i.e.
5484             // a sequence that is not constructed by trusted sources up to the that bad
5485             // actor's app.
5486             //   Note that passing your attribution source to another app means you allow
5487             // it to blame private data access on your app. This can be mediated by the OS
5488             // in, which case security is already enforced; by other app's code running in
5489             // your process calling into the other app, in which case it can already access
5490             // the private data in your process; or by you explicitly calling to another
5491             // app passing the source, in which case you must trust the other side;
5492 
5493             final int callingUid = Binder.getCallingUid();
5494             if (source.getUid() != callingUid && mContext.checkPermission(
5495                     Manifest.permission.UPDATE_APP_OPS_STATS, /*pid*/ -1, callingUid)
5496                     != PackageManager.PERMISSION_GRANTED) {
5497                 throw new SecurityException("Cannot register attribution source for uid:"
5498                         + source.getUid() + " from uid:" + callingUid);
5499             }
5500 
5501             final PackageManagerInternal packageManagerInternal = LocalServices.getService(
5502                     PackageManagerInternal.class);
5503             if (packageManagerInternal.getPackageUid(source.getPackageName(), 0,
5504                     UserHandle.getUserId(callingUid)) != source.getUid()) {
5505                 throw new SecurityException("Cannot register attribution source for package:"
5506                         + source.getPackageName() + " from uid:" + callingUid);
5507             }
5508 
5509             final AttributionSource next = source.getNext();
5510             if (next != null && next.getNext() != null
5511                     && !isRegisteredAttributionSource(next)) {
5512                 throw new SecurityException("Cannot register forged attribution source:"
5513                         + source);
5514             }
5515 
5516             synchronized (mLock) {
5517                 mAttributions.put(source.getToken(), source);
5518             }
5519         }
5520 
5521         public boolean isRegisteredAttributionSource(@NonNull AttributionSource source) {
5522             synchronized (mLock) {
5523                 final AttributionSource cachedSource = mAttributions.get(source.getToken());
5524                 if (cachedSource != null) {
5525                     return cachedSource.equals(source);
5526                 }
5527                 return false;
5528             }
5529         }
5530     }
5531 
5532     /**
5533      * TODO: We need to consolidate these APIs either on PermissionManager or an extension
5534      * object or a separate PermissionChecker service in context. The impartant part is to
5535      * keep a single impl that is exposed to Java and native. We are not sure about the
5536      * API shape so let is soak a bit.
5537      */
5538     private static final class PermissionCheckerService extends IPermissionChecker.Stub {
5539         // Cache for platform defined runtime permissions to avoid multi lookup (name -> info)
5540         private static final ConcurrentHashMap<String, PermissionInfo> sPlatformPermissions
5541                 = new ConcurrentHashMap<>();
5542 
5543         private static final AtomicInteger sAttributionChainIds = new AtomicInteger(0);
5544 
5545         private final @NonNull Context mContext;
5546         private final @NonNull AppOpsManager mAppOpsManager;
5547         private final @NonNull PermissionManagerServiceInternal mPermissionManagerServiceInternal;
5548 
5549         PermissionCheckerService(@NonNull Context context) {
5550             mContext = context;
5551             mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
5552             mPermissionManagerServiceInternal =
5553                     LocalServices.getService(PermissionManagerServiceInternal.class);
5554         }
5555 
5556         @Override
5557         @PermissionCheckerManager.PermissionResult
5558         public int checkPermission(@NonNull String permission,
5559                 @NonNull AttributionSourceState attributionSourceState, @Nullable String message,
5560                 boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource,
5561                 int attributedOp) {
5562             Objects.requireNonNull(permission);
5563             Objects.requireNonNull(attributionSourceState);
5564             final AttributionSource attributionSource = new AttributionSource(
5565                     attributionSourceState);
5566             final int result = checkPermission(mContext, mPermissionManagerServiceInternal,
5567                     permission, attributionSource, message, forDataDelivery, startDataDelivery,
5568                     fromDatasource, attributedOp);
5569             // Finish any started op if some step in the attribution chain failed.
5570             if (startDataDelivery && result != PermissionChecker.PERMISSION_GRANTED
5571                     && result != PermissionChecker.PERMISSION_SOFT_DENIED) {
5572                 if (attributedOp == AppOpsManager.OP_NONE) {
5573                     finishDataDelivery(AppOpsManager.permissionToOpCode(permission),
5574                             attributionSource.asState(), fromDatasource);
5575                 } else {
5576                     finishDataDelivery(attributedOp, attributionSource.asState(), fromDatasource);
5577                 }
5578             }
5579             return result;
5580         }
5581 
5582         @Override
5583         public void finishDataDelivery(int op,
5584                 @NonNull AttributionSourceState attributionSourceState, boolean fromDataSource) {
5585             finishDataDelivery(mContext, op, attributionSourceState,
5586                     fromDataSource);
5587         }
5588 
5589         private static void finishDataDelivery(Context context, int op,
5590                 @NonNull AttributionSourceState attributionSourceState, boolean fromDatasource) {
5591             Objects.requireNonNull(attributionSourceState);
5592             AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
5593 
5594             if (op == AppOpsManager.OP_NONE) {
5595                 return;
5596             }
5597 
5598             AttributionSource current = new AttributionSource(attributionSourceState);
5599             AttributionSource next = null;
5600 
5601             while (true) {
5602                 final boolean skipCurrentFinish = (fromDatasource || next != null);
5603 
5604                 next = current.getNext();
5605 
5606                 // If the call is from a datasource we need to vet only the chain before it. This
5607                 // way we can avoid the datasource creating an attribution context for every call.
5608                 if (!(fromDatasource && current.asState() == attributionSourceState)
5609                         && next != null && !current.isTrusted(context)) {
5610                     return;
5611                 }
5612 
5613                 // The access is for oneself if this is the single receiver of data
5614                 // after the data source or if this is the single attribution source
5615                 // in the chain if not from a datasource.
5616                 final boolean singleReceiverFromDatasource = (fromDatasource
5617                         && current.asState() == attributionSourceState && next != null
5618                         && next.getNext() == null);
5619                 final boolean selfAccess = singleReceiverFromDatasource || next == null;
5620 
5621                 final AttributionSource accessorSource = (!singleReceiverFromDatasource)
5622                         ? current : next;
5623 
5624                 if (selfAccess) {
5625                     final String resolvedPackageName = resolvePackageName(context, accessorSource);
5626                     if (resolvedPackageName == null) {
5627                         return;
5628                     }
5629                     appOpsManager.finishOp(accessorSource.getToken(), op,
5630                             accessorSource.getUid(), resolvedPackageName,
5631                             accessorSource.getAttributionTag());
5632                 } else {
5633                     final AttributionSource resolvedAttributionSource =
5634                             resolveAttributionSource(context, accessorSource);
5635                     if (resolvedAttributionSource.getPackageName() == null) {
5636                         return;
5637                     }
5638                     appOpsManager.finishProxyOp(AppOpsManager.opToPublicName(op),
5639                             resolvedAttributionSource, skipCurrentFinish);
5640                 }
5641 
5642                 if (next == null || next.getNext() == null) {
5643                     return;
5644                 }
5645 
5646                 RegisteredAttribution registered =
5647                         sRunningAttributionSources.remove(current.getToken());
5648                 if (registered != null) {
5649                     registered.unregister();
5650                 }
5651                 current = next;
5652             }
5653         }
5654 
5655         @Override
5656         @PermissionCheckerManager.PermissionResult
5657         public int checkOp(int op, AttributionSourceState attributionSource,
5658                 String message, boolean forDataDelivery, boolean startDataDelivery) {
5659             int result = checkOp(mContext, op, mPermissionManagerServiceInternal,
5660                     new AttributionSource(attributionSource), message, forDataDelivery,
5661                     startDataDelivery);
5662             if (result != PermissionChecker.PERMISSION_GRANTED && startDataDelivery) {
5663                 // Finish any started op if some step in the attribution chain failed.
5664                 finishDataDelivery(op, attributionSource, /*fromDatasource*/ false);
5665             }
5666             return result;
5667         }
5668 
5669         @PermissionCheckerManager.PermissionResult
5670         private static int checkPermission(@NonNull Context context,
5671                 @NonNull PermissionManagerServiceInternal permissionManagerServiceInt,
5672                 @NonNull String permission, @NonNull AttributionSource attributionSource,
5673                 @Nullable String message, boolean forDataDelivery, boolean startDataDelivery,
5674                 boolean fromDatasource, int attributedOp) {
5675             PermissionInfo permissionInfo = sPlatformPermissions.get(permission);
5676 
5677             if (permissionInfo == null) {
5678                 try {
5679                     permissionInfo = context.getPackageManager().getPermissionInfo(permission, 0);
5680                     if (PLATFORM_PACKAGE_NAME.equals(permissionInfo.packageName)) {
5681                         // Double addition due to concurrency is fine - the backing
5682                         // store is concurrent.
5683                         sPlatformPermissions.put(permission, permissionInfo);
5684                     }
5685                 } catch (PackageManager.NameNotFoundException ignored) {
5686                     return PermissionChecker.PERMISSION_HARD_DENIED;
5687                 }
5688             }
5689 
5690             if (permissionInfo.isAppOp()) {
5691                 return checkAppOpPermission(context, permissionManagerServiceInt, permission,
5692                         attributionSource, message, forDataDelivery, fromDatasource);
5693             }
5694             if (permissionInfo.isRuntime()) {
5695                 return checkRuntimePermission(context, permissionManagerServiceInt, permission,
5696                         attributionSource, message, forDataDelivery, startDataDelivery,
5697                         fromDatasource, attributedOp);
5698             }
5699 
5700             if (!fromDatasource && !checkPermission(context, permissionManagerServiceInt,
5701                     permission, attributionSource.getUid(),
5702                     attributionSource.getRenouncedPermissions())) {
5703                 return PermissionChecker.PERMISSION_HARD_DENIED;
5704             }
5705 
5706             if (attributionSource.getNext() != null) {
5707                 return checkPermission(context, permissionManagerServiceInt, permission,
5708                         attributionSource.getNext(), message, forDataDelivery, startDataDelivery,
5709                         /*fromDatasource*/ false, attributedOp);
5710             }
5711 
5712             return PermissionChecker.PERMISSION_GRANTED;
5713         }
5714 
5715         @PermissionCheckerManager.PermissionResult
5716         private static int checkAppOpPermission(@NonNull Context context,
5717                 @NonNull PermissionManagerServiceInternal permissionManagerServiceInt,
5718                 @NonNull String permission, @NonNull AttributionSource attributionSource,
5719                 @Nullable String message, boolean forDataDelivery, boolean fromDatasource) {
5720             final int op = AppOpsManager.permissionToOpCode(permission);
5721             if (op < 0) {
5722                 Slog.wtf(LOG_TAG, "Appop permission " + permission + " with no app op defined!");
5723                 return PermissionChecker.PERMISSION_HARD_DENIED;
5724             }
5725 
5726             AttributionSource current = attributionSource;
5727             AttributionSource next = null;
5728 
5729             while (true) {
5730                 final boolean skipCurrentChecks = (fromDatasource || next != null);
5731 
5732                 next = current.getNext();
5733 
5734                 // If the call is from a datasource we need to vet only the chain before it. This
5735                 // way we can avoid the datasource creating an attribution context for every call.
5736                 if (!(fromDatasource && current.equals(attributionSource))
5737                         && next != null && !current.isTrusted(context)) {
5738                     return PermissionChecker.PERMISSION_HARD_DENIED;
5739                 }
5740 
5741                 // The access is for oneself if this is the single receiver of data
5742                 // after the data source or if this is the single attribution source
5743                 // in the chain if not from a datasource.
5744                 final boolean singleReceiverFromDatasource = (fromDatasource
5745                         && current.equals(attributionSource) && next != null
5746                         && next.getNext() == null);
5747                 final boolean selfAccess = singleReceiverFromDatasource || next == null;
5748 
5749                 final int opMode = performOpTransaction(context, op, current, message,
5750                         forDataDelivery, /*startDataDelivery*/ false, skipCurrentChecks,
5751                         selfAccess, singleReceiverFromDatasource, AppOpsManager.OP_NONE,
5752                         AppOpsManager.ATTRIBUTION_FLAGS_NONE, AppOpsManager.ATTRIBUTION_FLAGS_NONE,
5753                         AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE);
5754 
5755                 switch (opMode) {
5756                     case AppOpsManager.MODE_IGNORED:
5757                     case AppOpsManager.MODE_ERRORED: {
5758                         return PermissionChecker.PERMISSION_HARD_DENIED;
5759                     }
5760                     case AppOpsManager.MODE_DEFAULT: {
5761                         if (!skipCurrentChecks && !checkPermission(context,
5762                                 permissionManagerServiceInt, permission, attributionSource.getUid(),
5763                                 attributionSource.getRenouncedPermissions())) {
5764                             return PermissionChecker.PERMISSION_HARD_DENIED;
5765                         }
5766                         if (next != null && !checkPermission(context, permissionManagerServiceInt,
5767                                 permission, next.getUid(), next.getRenouncedPermissions())) {
5768                             return PermissionChecker.PERMISSION_HARD_DENIED;
5769                         }
5770                     }
5771                 }
5772 
5773                 if (next == null || next.getNext() == null) {
5774                     return PermissionChecker.PERMISSION_GRANTED;
5775                 }
5776 
5777                 current = next;
5778             }
5779         }
5780 
5781         private static int checkRuntimePermission(@NonNull Context context,
5782                 @NonNull PermissionManagerServiceInternal permissionManagerServiceInt,
5783                 @NonNull String permission, @NonNull AttributionSource attributionSource,
5784                 @Nullable String message, boolean forDataDelivery, boolean startDataDelivery,
5785                 boolean fromDatasource, int attributedOp) {
5786             // Now let's check the identity chain...
5787             final int op = AppOpsManager.permissionToOpCode(permission);
5788             final int attributionChainId =
5789                     getAttributionChainId(startDataDelivery, attributionSource);
5790             final boolean hasChain = attributionChainId != ATTRIBUTION_CHAIN_ID_NONE;
5791             AttributionSource current = attributionSource;
5792             AttributionSource next = null;
5793             // We consider the chain trusted if the start node has UPDATE_APP_OPS_STATS, and
5794             // every attributionSource in the chain is registered with the system.
5795             final boolean isChainStartTrusted = !hasChain || checkPermission(context,
5796                     permissionManagerServiceInt, UPDATE_APP_OPS_STATS, current.getUid(),
5797                     current.getRenouncedPermissions());
5798 
5799             while (true) {
5800                 final boolean skipCurrentChecks = (fromDatasource || next != null);
5801                 next = current.getNext();
5802 
5803                 // If the call is from a datasource we need to vet only the chain before it. This
5804                 // way we can avoid the datasource creating an attribution context for every call.
5805                 if (!(fromDatasource && current.equals(attributionSource))
5806                         && next != null && !current.isTrusted(context)) {
5807                     return PermissionChecker.PERMISSION_HARD_DENIED;
5808                 }
5809 
5810                 // If we already checked the permission for this one, skip the work
5811                 if (!skipCurrentChecks && !checkPermission(context, permissionManagerServiceInt,
5812                         permission, current.getUid(), current.getRenouncedPermissions())) {
5813                     return PermissionChecker.PERMISSION_HARD_DENIED;
5814                 }
5815 
5816                 if (next != null && !checkPermission(context, permissionManagerServiceInt,
5817                         permission, next.getUid(), next.getRenouncedPermissions())) {
5818                     return PermissionChecker.PERMISSION_HARD_DENIED;
5819                 }
5820 
5821                 if (op < 0) {
5822                     // Bg location is one-off runtime modifier permission and has no app op
5823                     if (sPlatformPermissions.contains(permission)
5824                             && !Manifest.permission.ACCESS_BACKGROUND_LOCATION.equals(permission)) {
5825                         Slog.wtf(LOG_TAG, "Platform runtime permission " + permission
5826                                 + " with no app op defined!");
5827                     }
5828                     if (next == null) {
5829                         return PermissionChecker.PERMISSION_GRANTED;
5830                     }
5831                     current = next;
5832                     continue;
5833                 }
5834 
5835                 // The access is for oneself if this is the single receiver of data
5836                 // after the data source or if this is the single attribution source
5837                 // in the chain if not from a datasource.
5838                 final boolean singleReceiverFromDatasource = (fromDatasource
5839                         && current.equals(attributionSource)
5840                         && next != null && next.getNext() == null);
5841                 final boolean selfAccess = singleReceiverFromDatasource || next == null;
5842                 final boolean isLinkTrusted = isChainStartTrusted
5843                         && (current.isTrusted(context) || current.equals(attributionSource))
5844                         && (next == null || next.isTrusted(context));
5845 
5846                 final int proxyAttributionFlags = (!skipCurrentChecks && hasChain)
5847                         ? resolveProxyAttributionFlags(attributionSource, current, fromDatasource,
5848                                 startDataDelivery, selfAccess, isLinkTrusted)
5849                         : ATTRIBUTION_FLAGS_NONE;
5850                 final int proxiedAttributionFlags = hasChain ? resolveProxiedAttributionFlags(
5851                         attributionSource, next, fromDatasource, startDataDelivery, selfAccess,
5852                         isLinkTrusted) : ATTRIBUTION_FLAGS_NONE;
5853 
5854                 final int opMode = performOpTransaction(context, op, current, message,
5855                         forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess,
5856                         singleReceiverFromDatasource, attributedOp, proxyAttributionFlags,
5857                         proxiedAttributionFlags, attributionChainId);
5858 
5859                 switch (opMode) {
5860                     case AppOpsManager.MODE_ERRORED: {
5861                         return PermissionChecker.PERMISSION_HARD_DENIED;
5862                     }
5863                     case AppOpsManager.MODE_IGNORED: {
5864                         return PermissionChecker.PERMISSION_SOFT_DENIED;
5865                     }
5866                 }
5867 
5868                 if (startDataDelivery) {
5869                     RegisteredAttribution registered = new RegisteredAttribution(context, op,
5870                             current, fromDatasource);
5871                     sRunningAttributionSources.put(current.getToken(), registered);
5872                 }
5873 
5874                 if (next == null || next.getNext() == null) {
5875                     return PermissionChecker.PERMISSION_GRANTED;
5876                 }
5877 
5878                 current = next;
5879             }
5880         }
5881 
5882         private static boolean checkPermission(@NonNull Context context,
5883                 @NonNull PermissionManagerServiceInternal permissionManagerServiceInt,
5884                 @NonNull String permission, int uid, @NonNull Set<String> renouncedPermissions) {
5885             boolean permissionGranted = context.checkPermission(permission, /*pid*/ -1,
5886                     uid) == PackageManager.PERMISSION_GRANTED;
5887 
5888             // Override certain permissions checks for the HotwordDetectionService. This service is
5889             // an isolated service, which ordinarily cannot hold permissions.
5890             // There's probably a cleaner, more generalizable way to do this. For now, this is
5891             // the only use case for this, so simply override here.
5892             if (!permissionGranted
5893                     && Process.isIsolated(uid) // simple check which fails-fast for the common case
5894                     && (permission.equals(RECORD_AUDIO)
5895                     || permission.equals(CAPTURE_AUDIO_HOTWORD))) {
5896                 HotwordDetectionServiceProvider hotwordServiceProvider =
5897                         permissionManagerServiceInt.getHotwordDetectionServiceProvider();
5898                 permissionGranted = hotwordServiceProvider != null
5899                         && uid == hotwordServiceProvider.getUid();
5900             }
5901 
5902             if (permissionGranted && renouncedPermissions.contains(permission)
5903                     && context.checkPermission(Manifest.permission.RENOUNCE_PERMISSIONS,
5904                     /*pid*/ -1, uid) == PackageManager.PERMISSION_GRANTED) {
5905                 return false;
5906             }
5907             return permissionGranted;
5908         }
5909 
5910         private static @AttributionFlags int resolveProxyAttributionFlags(
5911                 @NonNull AttributionSource attributionChain,
5912                 @NonNull AttributionSource current, boolean fromDatasource,
5913                 boolean startDataDelivery, boolean selfAccess, boolean isTrusted) {
5914             return resolveAttributionFlags(attributionChain, current, fromDatasource,
5915                     startDataDelivery, selfAccess, isTrusted, /*flagsForProxy*/ true);
5916         }
5917 
5918         private static @AttributionFlags int resolveProxiedAttributionFlags(
5919                 @NonNull AttributionSource attributionChain,
5920                 @NonNull AttributionSource current, boolean fromDatasource,
5921                 boolean startDataDelivery, boolean selfAccess, boolean isTrusted) {
5922             return resolveAttributionFlags(attributionChain, current, fromDatasource,
5923                     startDataDelivery, selfAccess, isTrusted, /*flagsForProxy*/ false);
5924         }
5925 
5926         private static @AttributionFlags int resolveAttributionFlags(
5927                 @NonNull AttributionSource attributionChain,
5928                 @NonNull AttributionSource current, boolean fromDatasource,
5929                 boolean startDataDelivery, boolean selfAccess, boolean isTrusted,
5930                 boolean flagsForProxy) {
5931             if (current == null || !startDataDelivery) {
5932                 return AppOpsManager.ATTRIBUTION_FLAGS_NONE;
5933             }
5934             int trustedFlag = isTrusted
5935                     ? AppOpsManager.ATTRIBUTION_FLAG_TRUSTED : AppOpsManager.ATTRIBUTION_FLAGS_NONE;
5936             if (flagsForProxy) {
5937                 if (selfAccess) {
5938                     return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR;
5939                 } else if (!fromDatasource && current.equals(attributionChain)) {
5940                     return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR;
5941                 }
5942             } else {
5943                 if (selfAccess) {
5944                     return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_RECEIVER;
5945                 } else if (fromDatasource && current.equals(attributionChain.getNext())) {
5946                     return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR;
5947                 } else if (current.getNext() == null) {
5948                     return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_RECEIVER;
5949                 }
5950             }
5951             if (fromDatasource && current.equals(attributionChain)) {
5952                 return AppOpsManager.ATTRIBUTION_FLAGS_NONE;
5953             }
5954             return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_INTERMEDIARY;
5955         }
5956 
5957         private static int checkOp(@NonNull Context context, @NonNull int op,
5958                 @NonNull PermissionManagerServiceInternal permissionManagerServiceInt,
5959                 @NonNull AttributionSource attributionSource, @Nullable String message,
5960                 boolean forDataDelivery, boolean startDataDelivery) {
5961             if (op < 0 || attributionSource.getPackageName() == null) {
5962                 return PermissionChecker.PERMISSION_HARD_DENIED;
5963             }
5964 
5965             final int attributionChainId =
5966                     getAttributionChainId(startDataDelivery, attributionSource);
5967             final boolean hasChain = attributionChainId != ATTRIBUTION_CHAIN_ID_NONE;
5968 
5969             AttributionSource current = attributionSource;
5970             AttributionSource next = null;
5971 
5972             // We consider the chain trusted if the start node has UPDATE_APP_OPS_STATS, and
5973             // every attributionSource in the chain is registered with the system.
5974             final boolean isChainStartTrusted = !hasChain || checkPermission(context,
5975                     permissionManagerServiceInt, UPDATE_APP_OPS_STATS, current.getUid(),
5976                     current.getRenouncedPermissions());
5977 
5978             while (true) {
5979                 final boolean skipCurrentChecks = (next != null);
5980                 next = current.getNext();
5981 
5982                 // If the call is from a datasource we need to vet only the chain before it. This
5983                 // way we can avoid the datasource creating an attribution context for every call.
5984                 if (next != null && !current.isTrusted(context)) {
5985                     return PermissionChecker.PERMISSION_HARD_DENIED;
5986                 }
5987 
5988                 // The access is for oneself if this is the single attribution source in the chain.
5989                 final boolean selfAccess = (next == null);
5990                 final boolean isLinkTrusted = isChainStartTrusted
5991                         && (current.isTrusted(context) || current.equals(attributionSource))
5992                         && (next == null || next.isTrusted(context));
5993 
5994                 final int proxyAttributionFlags = (!skipCurrentChecks && hasChain)
5995                         ? resolveProxyAttributionFlags(attributionSource, current,
5996                                 /*fromDatasource*/ false, startDataDelivery, selfAccess,
5997                         isLinkTrusted) : ATTRIBUTION_FLAGS_NONE;
5998                 final int proxiedAttributionFlags = hasChain ? resolveProxiedAttributionFlags(
5999                         attributionSource, next, /*fromDatasource*/ false, startDataDelivery,
6000                         selfAccess, isLinkTrusted) : ATTRIBUTION_FLAGS_NONE;
6001 
6002                 final int opMode = performOpTransaction(context, op, current, message,
6003                         forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess,
6004                         /*fromDatasource*/ false, AppOpsManager.OP_NONE, proxyAttributionFlags,
6005                         proxiedAttributionFlags, attributionChainId);
6006 
6007                 switch (opMode) {
6008                     case AppOpsManager.MODE_ERRORED: {
6009                         return PermissionChecker.PERMISSION_HARD_DENIED;
6010                     }
6011                     case AppOpsManager.MODE_IGNORED: {
6012                         return PermissionChecker.PERMISSION_SOFT_DENIED;
6013                     }
6014                 }
6015 
6016                 if (next == null || next.getNext() == null) {
6017                     return PermissionChecker.PERMISSION_GRANTED;
6018                 }
6019 
6020                 current = next;
6021             }
6022         }
6023 
6024         @SuppressWarnings("ConstantConditions")
6025         private static int performOpTransaction(@NonNull Context context, int op,
6026                 @NonNull AttributionSource attributionSource, @Nullable String message,
6027                 boolean forDataDelivery, boolean startDataDelivery, boolean skipProxyOperation,
6028                 boolean selfAccess, boolean singleReceiverFromDatasource, int attributedOp,
6029                 @AttributionFlags int proxyAttributionFlags,
6030                 @AttributionFlags int proxiedAttributionFlags, int attributionChainId) {
6031             // We cannot perform app ops transactions without a package name. In all relevant
6032             // places we pass the package name but just in case there is a bug somewhere we
6033             // do a best effort to resolve the package from the UID (pick first without a loss
6034             // of generality - they are in the same security sandbox).
6035             final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
6036             final AttributionSource accessorSource = (!singleReceiverFromDatasource)
6037                     ? attributionSource : attributionSource.getNext();
6038             if (!forDataDelivery) {
6039                 final String resolvedAccessorPackageName = resolvePackageName(context,
6040                         accessorSource);
6041                 if (resolvedAccessorPackageName == null) {
6042                     return AppOpsManager.MODE_ERRORED;
6043                 }
6044                 final int opMode = appOpsManager.unsafeCheckOpRawNoThrow(op,
6045                         accessorSource.getUid(), resolvedAccessorPackageName);
6046                 final AttributionSource next = accessorSource.getNext();
6047                 if (!selfAccess && opMode == AppOpsManager.MODE_ALLOWED && next != null) {
6048                     final String resolvedNextPackageName = resolvePackageName(context, next);
6049                     if (resolvedNextPackageName == null) {
6050                         return AppOpsManager.MODE_ERRORED;
6051                     }
6052                     return appOpsManager.unsafeCheckOpRawNoThrow(op, next.getUid(),
6053                             resolvedNextPackageName);
6054                 }
6055                 return opMode;
6056             } else if (startDataDelivery) {
6057                 final AttributionSource resolvedAttributionSource = resolveAttributionSource(
6058                         context, accessorSource);
6059                 if (resolvedAttributionSource.getPackageName() == null) {
6060                     return AppOpsManager.MODE_ERRORED;
6061                 }
6062                 // If the datasource is not in a trusted platform component then in would not
6063                 // have UPDATE_APP_OPS_STATS and the call below would fail. The problem is that
6064                 // an app is exposing runtime permission protected data but cannot blame others
6065                 // in a trusted way which would not properly show in permission usage UIs.
6066                 // As a fallback we note a proxy op that blames the app and the datasource.
6067                 int startedOp = op;
6068                 int checkedOpResult = MODE_ALLOWED;
6069                 int startedOpResult;
6070 
6071                 // If the datasource wants to attribute to another app op we need to
6072                 // make sure the op for the permission and the attributed ops allow
6073                 // the operation. We return the less permissive of the two and check
6074                 // the permission op while start the attributed op.
6075                 if (attributedOp != AppOpsManager.OP_NONE && attributedOp != op) {
6076                     checkedOpResult = appOpsManager.checkOpNoThrow(op,
6077                             resolvedAttributionSource.getUid(), resolvedAttributionSource
6078                                     .getPackageName());
6079                     if (checkedOpResult == MODE_ERRORED) {
6080                         return checkedOpResult;
6081                     }
6082                     startedOp = attributedOp;
6083                 }
6084                 if (selfAccess) {
6085                     try {
6086                         startedOpResult = appOpsManager.startOpNoThrow(
6087                                 resolvedAttributionSource.getToken(), startedOp,
6088                                 resolvedAttributionSource.getUid(),
6089                                 resolvedAttributionSource.getPackageName(),
6090                                 /*startIfModeDefault*/ false,
6091                                 resolvedAttributionSource.getAttributionTag(),
6092                                 message, proxyAttributionFlags, attributionChainId);
6093                     } catch (SecurityException e) {
6094                         Slog.w(LOG_TAG, "Datasource " + attributionSource + " protecting data with"
6095                                 + " platform defined runtime permission "
6096                                 + AppOpsManager.opToPermission(op) + " while not having "
6097                                 + Manifest.permission.UPDATE_APP_OPS_STATS);
6098                         startedOpResult = appOpsManager.startProxyOpNoThrow(attributedOp,
6099                                 attributionSource, message, skipProxyOperation,
6100                                 proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
6101                     }
6102                 } else {
6103                     startedOpResult = appOpsManager.startProxyOpNoThrow(startedOp,
6104                             resolvedAttributionSource, message, skipProxyOperation,
6105                             proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
6106                 }
6107                 return Math.max(checkedOpResult, startedOpResult);
6108             } else {
6109                 final AttributionSource resolvedAttributionSource = resolveAttributionSource(
6110                         context, accessorSource);
6111                 if (resolvedAttributionSource.getPackageName() == null) {
6112                     return AppOpsManager.MODE_ERRORED;
6113                 }
6114                 int notedOp = op;
6115                 int checkedOpResult = MODE_ALLOWED;
6116                 int notedOpResult;
6117 
6118                 // If the datasource wants to attribute to another app op we need to
6119                 // make sure the op for the permission and the attributed ops allow
6120                 // the operation. We return the less permissive of the two and check
6121                 // the permission op while start the attributed op.
6122                 if (attributedOp != AppOpsManager.OP_NONE && attributedOp != op) {
6123                     checkedOpResult = appOpsManager.checkOpNoThrow(op,
6124                             resolvedAttributionSource.getUid(), resolvedAttributionSource
6125                                     .getPackageName());
6126                     if (checkedOpResult == MODE_ERRORED) {
6127                         return checkedOpResult;
6128                     }
6129                     notedOp = attributedOp;
6130                 }
6131                 if (selfAccess) {
6132                     // If the datasource is not in a trusted platform component then in would not
6133                     // have UPDATE_APP_OPS_STATS and the call below would fail. The problem is that
6134                     // an app is exposing runtime permission protected data but cannot blame others
6135                     // in a trusted way which would not properly show in permission usage UIs.
6136                     // As a fallback we note a proxy op that blames the app and the datasource.
6137                     try {
6138                         notedOpResult = appOpsManager.noteOpNoThrow(notedOp,
6139                                 resolvedAttributionSource.getUid(),
6140                                 resolvedAttributionSource.getPackageName(),
6141                                 resolvedAttributionSource.getAttributionTag(),
6142                                 message);
6143                     } catch (SecurityException e) {
6144                         Slog.w(LOG_TAG, "Datasource " + attributionSource + " protecting data with"
6145                                 + " platform defined runtime permission "
6146                                 + AppOpsManager.opToPermission(op) + " while not having "
6147                                 + Manifest.permission.UPDATE_APP_OPS_STATS);
6148                         notedOpResult = appOpsManager.noteProxyOpNoThrow(notedOp, attributionSource,
6149                                 message, skipProxyOperation);
6150                     }
6151                 } else {
6152                     notedOpResult = appOpsManager.noteProxyOpNoThrow(notedOp,
6153                             resolvedAttributionSource, message, skipProxyOperation);
6154                 }
6155                 return Math.max(checkedOpResult, notedOpResult);
6156             }
6157         }
6158 
6159         private static int getAttributionChainId(boolean startDataDelivery,
6160                 AttributionSource source) {
6161             if (source == null || source.getNext() == null || !startDataDelivery) {
6162                 return AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE;
6163             }
6164             int attributionChainId = sAttributionChainIds.incrementAndGet();
6165 
6166             // handle overflow
6167             if (attributionChainId < 0) {
6168                 attributionChainId = 0;
6169                 sAttributionChainIds.set(0);
6170             }
6171             return attributionChainId;
6172         }
6173 
6174         private static @Nullable String resolvePackageName(@NonNull Context context,
6175                 @NonNull AttributionSource attributionSource) {
6176             if (attributionSource.getPackageName() != null) {
6177                 return attributionSource.getPackageName();
6178             }
6179             final String[] packageNames = context.getPackageManager().getPackagesForUid(
6180                     attributionSource.getUid());
6181             if (packageNames != null) {
6182                 // This is best effort if the caller doesn't pass a package. The security
6183                 // sandbox is UID, therefore we pick an arbitrary package.
6184                 return packageNames[0];
6185             }
6186             // Last resort to handle special UIDs like root, etc.
6187             return AppOpsManager.resolvePackageName(attributionSource.getUid(),
6188                     attributionSource.getPackageName());
6189         }
6190 
6191         private static @NonNull AttributionSource resolveAttributionSource(
6192                 @NonNull Context context, @NonNull AttributionSource attributionSource) {
6193             if (attributionSource.getPackageName() != null) {
6194                 return attributionSource;
6195             }
6196             return attributionSource.withPackageName(resolvePackageName(context,
6197                     attributionSource));
6198         }
6199     }
6200 
6201     private static final class RegisteredAttribution {
6202         private final DeathRecipient mDeathRecipient;
6203         private final IBinder mToken;
6204         private final AtomicBoolean mFinished;
6205 
6206         RegisteredAttribution(Context context, int op, AttributionSource source,
6207                 boolean fromDatasource) {
6208             mFinished = new AtomicBoolean(false);
6209             mDeathRecipient = () -> {
6210                 if (unregister()) {
6211                     PermissionCheckerService
6212                             .finishDataDelivery(context, op, source.asState(), fromDatasource);
6213                 }
6214             };
6215             mToken = source.getToken();
6216             if (mToken != null) {
6217                 try {
6218                     mToken.linkToDeath(mDeathRecipient, 0);
6219                 } catch (RemoteException e) {
6220                     mDeathRecipient.binderDied();
6221                 }
6222             }
6223         }
6224 
6225         public boolean unregister() {
6226             if (mFinished.compareAndSet(false, true)) {
6227                 try {
6228                     if (mToken != null) {
6229                         mToken.unlinkToDeath(mDeathRecipient, 0);
6230                     }
6231                 } catch (NoSuchElementException e) {
6232                     // do nothing
6233                 }
6234                 return true;
6235             }
6236             return false;
6237         }
6238     }
6239 }
6240