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.CAMERA;
20 import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
21 import static android.Manifest.permission.CAPTURE_AUDIO_OUTPUT;
22 import static android.Manifest.permission.RECORD_AUDIO;
23 import static android.Manifest.permission.UPDATE_APP_OPS_STATS;
24 import static android.app.AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE;
25 import static android.app.AppOpsManager.ATTRIBUTION_FLAGS_NONE;
26 import static android.app.AppOpsManager.MODE_ALLOWED;
27 import static android.app.AppOpsManager.MODE_ERRORED;
28 import static android.app.AppOpsManager.MODE_IGNORED;
29 import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISALLOWED;
30 import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISCOURAGED;
31 
32 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
33 
34 import android.Manifest;
35 import android.annotation.AppIdInt;
36 import android.annotation.NonNull;
37 import android.annotation.Nullable;
38 import android.annotation.UserIdInt;
39 import android.app.ActivityManager;
40 import android.app.AppOpsManager;
41 import android.app.AppOpsManager.AttributionFlags;
42 import android.app.IActivityManager;
43 import android.content.AttributionSource;
44 import android.content.AttributionSourceState;
45 import android.content.Context;
46 import android.content.PermissionChecker;
47 import android.content.pm.FeatureInfo;
48 import android.content.pm.PackageManager;
49 import android.content.pm.PackageManagerInternal;
50 import android.content.pm.ParceledListSlice;
51 import android.content.pm.PermissionGroupInfo;
52 import android.content.pm.PermissionInfo;
53 import android.content.pm.permission.SplitPermissionInfoParcelable;
54 import android.health.connect.HealthConnectManager;
55 import android.os.Binder;
56 import android.os.IBinder;
57 import android.os.Process;
58 import android.os.RemoteException;
59 import android.os.ServiceManager;
60 import android.os.UserHandle;
61 import android.permission.IOnPermissionsChangeListener;
62 import android.permission.IPermissionChecker;
63 import android.permission.IPermissionManager;
64 import android.permission.PermissionCheckerManager;
65 import android.permission.PermissionManager;
66 import android.permission.PermissionManagerInternal;
67 import android.service.voice.VoiceInteractionManagerInternal;
68 import android.util.ArrayMap;
69 import android.util.Slog;
70 import android.util.SparseArray;
71 
72 import com.android.internal.annotations.GuardedBy;
73 import com.android.internal.util.Preconditions;
74 import com.android.internal.util.function.TriFunction;
75 import com.android.server.LocalServices;
76 import com.android.server.pm.UserManagerInternal;
77 import com.android.server.pm.UserManagerService;
78 import com.android.server.pm.permission.PermissionManagerServiceInternal.HotwordDetectionServiceProvider;
79 import com.android.server.pm.pkg.AndroidPackage;
80 import com.android.server.pm.pkg.PackageState;
81 
82 import java.util.ArrayList;
83 import java.util.Collections;
84 import java.util.List;
85 import java.util.Map;
86 import java.util.NoSuchElementException;
87 import java.util.Objects;
88 import java.util.Set;
89 import java.util.WeakHashMap;
90 import java.util.concurrent.ConcurrentHashMap;
91 import java.util.concurrent.atomic.AtomicBoolean;
92 import java.util.concurrent.atomic.AtomicInteger;
93 import java.util.function.BiFunction;
94 
95 /**
96  * Manages all permissions and handles permissions related tasks.
97  */
98 public class PermissionManagerService extends IPermissionManager.Stub {
99 
100     private static final String LOG_TAG = PermissionManagerService.class.getSimpleName();
101 
102     /** Map of IBinder -> Running AttributionSource */
103     private static final ConcurrentHashMap<IBinder, RegisteredAttribution>
104             sRunningAttributionSources = new ConcurrentHashMap<>();
105 
106     /** Lock to protect internal data access */
107     private final Object mLock = new Object();
108 
109     /** Internal connection to the package manager */
110     private final PackageManagerInternal mPackageManagerInt;
111 
112     /** Internal connection to the user manager */
113     private final UserManagerInternal mUserManagerInt;
114 
115     /** Map of OneTimePermissionUserManagers keyed by userId */
116     @GuardedBy("mLock")
117     @NonNull
118     private final SparseArray<OneTimePermissionUserManager> mOneTimePermissionUserManagers =
119             new SparseArray<>();
120 
121     /** App ops manager */
122     private final AppOpsManager mAppOpsManager;
123 
124     private final Context mContext;
125     private final PermissionManagerServiceInterface mPermissionManagerServiceImpl;
126 
127     @NonNull
128     private final AttributionSourceRegistry mAttributionSourceRegistry;
129 
130     @GuardedBy("mLock")
131     private CheckPermissionDelegate mCheckPermissionDelegate;
132 
133     @Nullable
134     private HotwordDetectionServiceProvider mHotwordDetectionServiceProvider;
135 
PermissionManagerService(@onNull Context context, @NonNull ArrayMap<String, FeatureInfo> availableFeatures)136     PermissionManagerService(@NonNull Context context,
137             @NonNull ArrayMap<String, FeatureInfo> availableFeatures) {
138         // The package info cache is the cache for package and permission information.
139         // Disable the package info and package permission caches locally but leave the
140         // checkPermission cache active.
141         PackageManager.invalidatePackageInfoCache();
142         PermissionManager.disablePackageNamePermissionCache();
143 
144         mContext = context;
145         mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
146         mUserManagerInt = LocalServices.getService(UserManagerInternal.class);
147         mAppOpsManager = context.getSystemService(AppOpsManager.class);
148 
149         mAttributionSourceRegistry = new AttributionSourceRegistry(context);
150 
151         PermissionManagerServiceInternalImpl localService =
152                 new PermissionManagerServiceInternalImpl();
153         LocalServices.addService(PermissionManagerServiceInternal.class, localService);
154         LocalServices.addService(PermissionManagerInternal.class, localService);
155 
156         mPermissionManagerServiceImpl = new PermissionManagerServiceImpl(context,
157                 availableFeatures);
158         //mPermissionManagerServiceImpl = new PermissionManagerServiceLoggingDecorator(
159         //        LocalServices.getService(PermissionManagerServiceInterface.class));
160     }
161 
162     /**
163      * Creates and returns an initialized, internal service for use by other components.
164      * <p>
165      * The object returned is identical to the one returned by the LocalServices class using:
166      * {@code LocalServices.getService(PermissionManagerServiceInternal.class);}
167      * <p>
168      * NOTE: The external lock is temporary and should be removed. This needs to be a
169      * lock created by the permission manager itself.
170      */
171     @NonNull
create(@onNull Context context, ArrayMap<String, FeatureInfo> availableFeatures)172     public static PermissionManagerServiceInternal create(@NonNull Context context,
173             ArrayMap<String, FeatureInfo> availableFeatures) {
174         final PermissionManagerServiceInternal permMgrInt =
175                 LocalServices.getService(PermissionManagerServiceInternal.class);
176         if (permMgrInt != null) {
177             return permMgrInt;
178         }
179         PermissionManagerService permissionService =
180                 (PermissionManagerService) ServiceManager.getService("permissionmgr");
181         if (permissionService == null) {
182             permissionService = new PermissionManagerService(context, availableFeatures);
183             ServiceManager.addService("permissionmgr", permissionService);
184             ServiceManager.addService("permission_checker", new PermissionCheckerService(context));
185         }
186         return LocalServices.getService(PermissionManagerServiceInternal.class);
187     }
188 
189     /**
190      * TODO: theianchen we want to remove this method in the future.
191      * There's a complete copy of this method in PermissionManagerServiceImpl
192      *
193      * This method should typically only be used when granting or revoking
194      * permissions, since the app may immediately restart after this call.
195      * <p>
196      * If you're doing surgery on app code/data, use {@link PackageFreezer} to
197      * guard your work against the app being relaunched.
198      */
killUid(int appId, int userId, String reason)199     public static void killUid(int appId, int userId, String reason) {
200         final long identity = Binder.clearCallingIdentity();
201         try {
202             IActivityManager am = ActivityManager.getService();
203             if (am != null) {
204                 try {
205                     am.killUidForPermissionChange(appId, userId, reason);
206                 } catch (RemoteException e) {
207                     /* ignore - same process */
208                 }
209             }
210         } finally {
211             Binder.restoreCallingIdentity(identity);
212         }
213     }
214 
checkPermission(String pkgName, String permName, @UserIdInt int userId)215     private int checkPermission(String pkgName, String permName, @UserIdInt int userId) {
216         // Not using Objects.requireNonNull() here for compatibility reasons.
217         if (pkgName == null || permName == null) {
218             return PackageManager.PERMISSION_DENIED;
219         }
220 
221         final CheckPermissionDelegate checkPermissionDelegate;
222         synchronized (mLock) {
223             checkPermissionDelegate = mCheckPermissionDelegate;
224         }
225 
226         if (checkPermissionDelegate == null) {
227             return mPermissionManagerServiceImpl.checkPermission(pkgName, permName, userId);
228         }
229         return checkPermissionDelegate.checkPermission(pkgName, permName, userId,
230                 mPermissionManagerServiceImpl::checkPermission);
231     }
232 
checkUidPermission(int uid, String permName)233     private int checkUidPermission(int uid, String permName) {
234         // Not using Objects.requireNonNull() here for compatibility reasons.
235         if (permName == null) {
236             return PackageManager.PERMISSION_DENIED;
237         }
238 
239         final CheckPermissionDelegate checkPermissionDelegate;
240         synchronized (mLock) {
241             checkPermissionDelegate = mCheckPermissionDelegate;
242         }
243 
244         if (checkPermissionDelegate == null)  {
245             return mPermissionManagerServiceImpl.checkUidPermission(uid, permName);
246         }
247         return checkPermissionDelegate.checkUidPermission(uid, permName,
248                 mPermissionManagerServiceImpl::checkUidPermission);
249     }
250 
251     @Override
setAutoRevokeExempted( @onNull String packageName, boolean exempted, int userId)252     public boolean setAutoRevokeExempted(
253             @NonNull String packageName, boolean exempted, int userId) {
254         Objects.requireNonNull(packageName);
255 
256         final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
257         final int callingUid = Binder.getCallingUid();
258 
259         if (!checkAutoRevokeAccess(pkg, callingUid)) {
260             return false;
261         }
262 
263         return setAutoRevokeExemptedInternal(pkg, exempted, userId);
264     }
265 
setAutoRevokeExemptedInternal(@onNull AndroidPackage pkg, boolean exempted, @UserIdInt int userId)266     private boolean setAutoRevokeExemptedInternal(@NonNull AndroidPackage pkg, boolean exempted,
267             @UserIdInt int userId) {
268         final int packageUid = UserHandle.getUid(userId, pkg.getUid());
269         if (mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_AUTO_REVOKE_MANAGED_BY_INSTALLER,
270                 packageUid, pkg.getPackageName()) != MODE_ALLOWED) {
271             // Allowlist user set - don't override
272             return false;
273         }
274 
275         final long identity = Binder.clearCallingIdentity();
276         try {
277             mAppOpsManager.setMode(AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, packageUid,
278                     pkg.getPackageName(), exempted ? MODE_IGNORED : MODE_ALLOWED);
279         } finally {
280             Binder.restoreCallingIdentity(identity);
281         }
282         return true;
283     }
284 
checkAutoRevokeAccess(AndroidPackage pkg, int callingUid)285     private boolean checkAutoRevokeAccess(AndroidPackage pkg, int callingUid) {
286         final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
287                 Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS)
288                 == PackageManager.PERMISSION_GRANTED;
289         final boolean isCallerInstallerOnRecord =
290                 mPackageManagerInt.isCallerInstallerOfRecord(pkg, callingUid);
291 
292         if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
293             throw new SecurityException("Caller must either hold "
294                     + Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS
295                     + " or be the installer on record");
296         }
297 
298         if (pkg == null || mPackageManagerInt.filterAppAccess(pkg, callingUid,
299                 UserHandle.getUserId(callingUid))) {
300             return false;
301         }
302 
303         return true;
304     }
305 
306     @Override
isAutoRevokeExempted(@onNull String packageName, int userId)307     public boolean isAutoRevokeExempted(@NonNull String packageName, int userId) {
308         Objects.requireNonNull(packageName);
309 
310         final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
311         final int callingUid = Binder.getCallingUid();
312 
313         if (!checkAutoRevokeAccess(pkg, callingUid)) {
314             return false;
315         }
316 
317         final int packageUid = UserHandle.getUid(userId, pkg.getUid());
318 
319         final long identity = Binder.clearCallingIdentity();
320         try {
321             return mAppOpsManager.checkOpNoThrow(
322                     AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, packageUid, packageName)
323                     == MODE_IGNORED;
324         } finally {
325             Binder.restoreCallingIdentity(identity);
326         }
327     }
328 
startShellPermissionIdentityDelegationInternal(int uid, @NonNull String packageName, @Nullable List<String> permissionNames)329     private void startShellPermissionIdentityDelegationInternal(int uid,
330             @NonNull String packageName, @Nullable List<String> permissionNames) {
331         synchronized (mLock) {
332             final CheckPermissionDelegate oldDelegate = mCheckPermissionDelegate;
333             if (oldDelegate != null && oldDelegate.getDelegatedUid() != uid) {
334                 throw new SecurityException(
335                         "Shell can delegate permissions only to one UID at a time");
336             }
337             final ShellDelegate delegate = new ShellDelegate(uid, packageName, permissionNames);
338             setCheckPermissionDelegateLocked(delegate);
339         }
340     }
341 
stopShellPermissionIdentityDelegationInternal()342     private void stopShellPermissionIdentityDelegationInternal() {
343         synchronized (mLock) {
344             setCheckPermissionDelegateLocked(null);
345         }
346     }
347 
348     @Nullable
getDelegatedShellPermissionsInternal()349     private List<String> getDelegatedShellPermissionsInternal() {
350         synchronized (mLock) {
351             if (mCheckPermissionDelegate == null) {
352                 return Collections.EMPTY_LIST;
353             }
354             return mCheckPermissionDelegate.getDelegatedPermissionNames();
355         }
356     }
357 
setCheckPermissionDelegateLocked(@ullable CheckPermissionDelegate delegate)358     private void setCheckPermissionDelegateLocked(@Nullable CheckPermissionDelegate delegate) {
359         if (delegate != null || mCheckPermissionDelegate != null) {
360             PackageManager.invalidatePackageInfoCache();
361         }
362         mCheckPermissionDelegate = delegate;
363     }
364 
365     @NonNull
getOneTimePermissionUserManager(@serIdInt int userId)366     private OneTimePermissionUserManager getOneTimePermissionUserManager(@UserIdInt int userId) {
367         OneTimePermissionUserManager oneTimePermissionUserManager;
368         synchronized (mLock) {
369             oneTimePermissionUserManager = mOneTimePermissionUserManagers.get(userId);
370             if (oneTimePermissionUserManager != null) {
371                 return oneTimePermissionUserManager;
372             }
373         }
374         // We cannot create a new instance of OneTimePermissionUserManager while holding our own
375         // lock, which may lead to a deadlock with the package manager lock. So we do it in a
376         // retry-like way, and just discard the newly created instance if someone else managed to be
377         // a little bit faster than us when we dropped our own lock.
378         final OneTimePermissionUserManager newOneTimePermissionUserManager =
379                 new OneTimePermissionUserManager(mContext.createContextAsUser(UserHandle.of(userId),
380                         /*flags*/ 0));
381         synchronized (mLock) {
382             oneTimePermissionUserManager = mOneTimePermissionUserManagers.get(userId);
383             if (oneTimePermissionUserManager != null) {
384                 return oneTimePermissionUserManager;
385             }
386             oneTimePermissionUserManager = newOneTimePermissionUserManager;
387             mOneTimePermissionUserManagers.put(userId, oneTimePermissionUserManager);
388         }
389         oneTimePermissionUserManager.registerUninstallListener();
390         return oneTimePermissionUserManager;
391     }
392 
393     @Override
startOneTimePermissionSession(String packageName, @UserIdInt int userId, long timeoutMillis, long revokeAfterKilledDelayMillis)394     public void startOneTimePermissionSession(String packageName, @UserIdInt int userId,
395             long timeoutMillis, long revokeAfterKilledDelayMillis) {
396         mContext.enforceCallingOrSelfPermission(
397                 Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS,
398                 "Must hold " + Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS
399                         + " to register permissions as one time.");
400         Objects.requireNonNull(packageName);
401 
402         final long token = Binder.clearCallingIdentity();
403         try {
404             getOneTimePermissionUserManager(userId).startPackageOneTimeSession(packageName,
405                     timeoutMillis, revokeAfterKilledDelayMillis);
406         } finally {
407             Binder.restoreCallingIdentity(token);
408         }
409     }
410 
411     @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS)
412     @Override
stopOneTimePermissionSession(String packageName, @UserIdInt int userId)413     public void stopOneTimePermissionSession(String packageName, @UserIdInt int userId) {
414         super.stopOneTimePermissionSession_enforcePermission();
415 
416         Objects.requireNonNull(packageName);
417 
418         final long token = Binder.clearCallingIdentity();
419         try {
420             getOneTimePermissionUserManager(userId).stopPackageOneTimeSession(packageName);
421         } finally {
422             Binder.restoreCallingIdentity(token);
423         }
424     }
425 
426     @Override
registerAttributionSource(@onNull AttributionSourceState source)427     public void registerAttributionSource(@NonNull AttributionSourceState source) {
428         mAttributionSourceRegistry
429                 .registerAttributionSource(new AttributionSource(source));
430     }
431 
432     @Override
isRegisteredAttributionSource(@onNull AttributionSourceState source)433     public boolean isRegisteredAttributionSource(@NonNull AttributionSourceState source) {
434         return mAttributionSourceRegistry
435                 .isRegisteredAttributionSource(new AttributionSource(source));
436     }
437 
438     @Override
getAutoRevokeExemptionRequestedPackages(int userId)439     public List<String> getAutoRevokeExemptionRequestedPackages(int userId) {
440         return getPackagesWithAutoRevokePolicy(AUTO_REVOKE_DISCOURAGED, userId);
441     }
442 
443     @Override
getAutoRevokeExemptionGrantedPackages(int userId)444     public List<String> getAutoRevokeExemptionGrantedPackages(int userId) {
445         return getPackagesWithAutoRevokePolicy(AUTO_REVOKE_DISALLOWED, userId);
446     }
447 
448     @NonNull
getPackagesWithAutoRevokePolicy(int autoRevokePolicy, int userId)449     private List<String> getPackagesWithAutoRevokePolicy(int autoRevokePolicy, int userId) {
450         mContext.enforceCallingPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
451                 "Must hold " + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY);
452 
453         List<String> result = new ArrayList<>();
454         mPackageManagerInt.forEachInstalledPackage(pkg -> {
455             if (pkg.getAutoRevokePermissions() == autoRevokePolicy) {
456                 result.add(pkg.getPackageName());
457             }
458         }, userId);
459         return result;
460     }
461 
462     /* Start of delegate methods to PermissionManagerServiceInterface */
463 
464     @Override
getAllPermissionGroups(int flags)465     public ParceledListSlice<PermissionGroupInfo> getAllPermissionGroups(int flags) {
466         return new ParceledListSlice<>(mPermissionManagerServiceImpl.getAllPermissionGroups(flags));
467     }
468 
469     @Override
getPermissionGroupInfo(String groupName, int flags)470     public PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags) {
471         return mPermissionManagerServiceImpl.getPermissionGroupInfo(groupName, flags);
472     }
473 
474     @Override
getPermissionInfo(String permissionName, String packageName, int flags)475     public PermissionInfo getPermissionInfo(String permissionName, String packageName, int flags) {
476         return mPermissionManagerServiceImpl.getPermissionInfo(permissionName, flags, packageName);
477     }
478 
479     @Override
queryPermissionsByGroup(String groupName, int flags)480     public ParceledListSlice<PermissionInfo> queryPermissionsByGroup(String groupName, int flags) {
481         List<PermissionInfo> permissionInfo =
482                 mPermissionManagerServiceImpl.queryPermissionsByGroup(groupName, flags);
483         if (permissionInfo == null) {
484             return null;
485         }
486 
487         return new ParceledListSlice<>(permissionInfo);
488     }
489 
490     @Override
addPermission(PermissionInfo permissionInfo, boolean async)491     public boolean addPermission(PermissionInfo permissionInfo, boolean async) {
492         return mPermissionManagerServiceImpl.addPermission(permissionInfo, async);
493     }
494 
495     @Override
removePermission(String permissionName)496     public void removePermission(String permissionName) {
497         mPermissionManagerServiceImpl.removePermission(permissionName);
498     }
499 
500     @Override
getPermissionFlags(String packageName, String permissionName, int userId)501     public int getPermissionFlags(String packageName, String permissionName, int userId) {
502         return mPermissionManagerServiceImpl
503                 .getPermissionFlags(packageName, permissionName, userId);
504     }
505 
506     @Override
updatePermissionFlags(String packageName, String permissionName, int flagMask, int flagValues, boolean checkAdjustPolicyFlagPermission, int userId)507     public void updatePermissionFlags(String packageName, String permissionName, int flagMask,
508             int flagValues, boolean checkAdjustPolicyFlagPermission, int userId) {
509         mPermissionManagerServiceImpl.updatePermissionFlags(packageName, permissionName, flagMask,
510                 flagValues, checkAdjustPolicyFlagPermission, userId);
511     }
512 
513     @Override
updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId)514     public void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId) {
515         mPermissionManagerServiceImpl.updatePermissionFlagsForAllApps(flagMask, flagValues, userId);
516     }
517 
518     @Override
addOnPermissionsChangeListener(IOnPermissionsChangeListener listener)519     public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
520         mPermissionManagerServiceImpl.addOnPermissionsChangeListener(listener);
521     }
522 
523     @Override
removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener)524     public void removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
525         mPermissionManagerServiceImpl.removeOnPermissionsChangeListener(listener);
526     }
527 
528     @Override
getAllowlistedRestrictedPermissions(String packageName, int flags, int userId)529     public List<String> getAllowlistedRestrictedPermissions(String packageName,
530             int flags, int userId) {
531         return mPermissionManagerServiceImpl.getAllowlistedRestrictedPermissions(packageName,
532                 flags, userId);
533     }
534 
535     @Override
addAllowlistedRestrictedPermission(String packageName, String permissionName, int flags, int userId)536     public boolean addAllowlistedRestrictedPermission(String packageName, String permissionName,
537             int flags, int userId) {
538         return mPermissionManagerServiceImpl.addAllowlistedRestrictedPermission(packageName,
539                 permissionName, flags, userId);
540     }
541 
542     @Override
removeAllowlistedRestrictedPermission(String packageName, String permissionName, int flags, int userId)543     public boolean removeAllowlistedRestrictedPermission(String packageName, String permissionName,
544             int flags, int userId) {
545         return mPermissionManagerServiceImpl.removeAllowlistedRestrictedPermission(packageName,
546                 permissionName, flags, userId);
547     }
548 
549     @Override
grantRuntimePermission(String packageName, String permissionName, int userId)550     public void grantRuntimePermission(String packageName, String permissionName, int userId) {
551         mPermissionManagerServiceImpl.grantRuntimePermission(packageName, permissionName, userId);
552     }
553 
554     @Override
revokeRuntimePermission(String packageName, String permissionName, int userId, String reason)555     public void revokeRuntimePermission(String packageName, String permissionName, int userId,
556             String reason) {
557         mPermissionManagerServiceImpl.revokeRuntimePermission(packageName, permissionName, userId,
558                 reason);
559     }
560 
561     @Override
revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId)562     public void revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId) {
563         mPermissionManagerServiceImpl.revokePostNotificationPermissionWithoutKillForTest(
564                 packageName, userId);
565     }
566 
567     @Override
shouldShowRequestPermissionRationale(String packageName, String permissionName, int userId)568     public boolean shouldShowRequestPermissionRationale(String packageName, String permissionName,
569             int userId) {
570         return mPermissionManagerServiceImpl.shouldShowRequestPermissionRationale(packageName,
571                 permissionName, userId);
572     }
573 
574     @Override
isPermissionRevokedByPolicy(String packageName, String permissionName, int userId)575     public boolean isPermissionRevokedByPolicy(String packageName, String permissionName,
576             int userId) {
577         return mPermissionManagerServiceImpl
578                 .isPermissionRevokedByPolicy(packageName, permissionName, userId);
579     }
580 
581     @Override
getSplitPermissions()582     public List<SplitPermissionInfoParcelable> getSplitPermissions() {
583         return mPermissionManagerServiceImpl.getSplitPermissions();
584     }
585 
586     /* End of delegate methods to PermissionManagerServiceInterface */
587 
588     private class PermissionManagerServiceInternalImpl implements PermissionManagerServiceInternal {
589         @Override
checkPermission(@onNull String packageName, @NonNull String permissionName, @UserIdInt int userId)590         public int checkPermission(@NonNull String packageName, @NonNull String permissionName,
591                 @UserIdInt int userId) {
592             return PermissionManagerService.this.checkPermission(packageName, permissionName,
593                     userId);
594         }
595 
596         @Override
checkUidPermission(int uid, @NonNull String permissionName)597         public int checkUidPermission(int uid, @NonNull String permissionName) {
598             return PermissionManagerService.this.checkUidPermission(uid, permissionName);
599         }
600 
601         @Override
startShellPermissionIdentityDelegation(int uid, @NonNull String packageName, @Nullable List<String> permissionNames)602         public void startShellPermissionIdentityDelegation(int uid, @NonNull String packageName,
603                 @Nullable List<String> permissionNames) {
604             Objects.requireNonNull(packageName, "packageName");
605             startShellPermissionIdentityDelegationInternal(uid, packageName, permissionNames);
606         }
607 
608         @Override
stopShellPermissionIdentityDelegation()609         public void stopShellPermissionIdentityDelegation() {
610             stopShellPermissionIdentityDelegationInternal();
611         }
612 
613         @Override
614         @NonNull
getDelegatedShellPermissions()615         public List<String> getDelegatedShellPermissions() {
616             return getDelegatedShellPermissionsInternal();
617         }
618 
619         @Override
setHotwordDetectionServiceProvider(HotwordDetectionServiceProvider provider)620         public void setHotwordDetectionServiceProvider(HotwordDetectionServiceProvider provider) {
621             mHotwordDetectionServiceProvider = provider;
622         }
623 
624         @Override
getHotwordDetectionServiceProvider()625         public HotwordDetectionServiceProvider getHotwordDetectionServiceProvider() {
626             return mHotwordDetectionServiceProvider;
627         }
628 
629         /* Start of delegate methods to PermissionManagerServiceInterface */
630 
631         @NonNull
632         @Override
getGidsForUid(int uid)633         public int[] getGidsForUid(int uid) {
634             return mPermissionManagerServiceImpl.getGidsForUid(uid);
635         }
636 
637         @NonNull
638         @Override
getAllAppOpPermissionPackages()639         public Map<String, Set<String>> getAllAppOpPermissionPackages() {
640             return mPermissionManagerServiceImpl.getAllAppOpPermissionPackages();
641         }
642 
643         @Override
onUserCreated(@serIdInt int userId)644         public void onUserCreated(@UserIdInt int userId) {
645             mPermissionManagerServiceImpl.onUserCreated(userId);
646         }
647 
648         @NonNull
649         @Override
getLegacyPermissions()650         public List<LegacyPermission> getLegacyPermissions() {
651             return mPermissionManagerServiceImpl.getLegacyPermissions();
652         }
653 
654         @NonNull
655         @Override
getLegacyPermissionState(@ppIdInt int appId)656         public LegacyPermissionState getLegacyPermissionState(@AppIdInt int appId) {
657             return mPermissionManagerServiceImpl.getLegacyPermissionState(appId);
658         }
659 
660         @Nullable
661         @Override
backupRuntimePermissions(@serIdInt int userId)662         public byte[] backupRuntimePermissions(@UserIdInt int userId) {
663             return mPermissionManagerServiceImpl.backupRuntimePermissions(userId);
664         }
665 
666         @Override
restoreRuntimePermissions(@onNull byte[] backup, @UserIdInt int userId)667         public void restoreRuntimePermissions(@NonNull byte[] backup, @UserIdInt int userId) {
668             mPermissionManagerServiceImpl.restoreRuntimePermissions(backup, userId);
669         }
670 
671         @Override
restoreDelayedRuntimePermissions(@onNull String packageName, @UserIdInt int userId)672         public void restoreDelayedRuntimePermissions(@NonNull String packageName,
673                 @UserIdInt int userId) {
674             mPermissionManagerServiceImpl.restoreDelayedRuntimePermissions(packageName, userId);
675         }
676 
677         @Override
readLegacyPermissionsTEMP( @onNull LegacyPermissionSettings legacyPermissionSettings)678         public void readLegacyPermissionsTEMP(
679                 @NonNull LegacyPermissionSettings legacyPermissionSettings) {
680             mPermissionManagerServiceImpl.readLegacyPermissionsTEMP(legacyPermissionSettings);
681         }
682 
683         @Override
writeLegacyPermissionsTEMP( @onNull LegacyPermissionSettings legacyPermissionSettings)684         public void writeLegacyPermissionsTEMP(
685                 @NonNull LegacyPermissionSettings legacyPermissionSettings) {
686             mPermissionManagerServiceImpl.writeLegacyPermissionsTEMP(legacyPermissionSettings);
687         }
688 
689         @Override
onPackageAdded(@onNull PackageState packageState, boolean isInstantApp, @Nullable AndroidPackage oldPkg)690         public void onPackageAdded(@NonNull PackageState packageState, boolean isInstantApp,
691                 @Nullable AndroidPackage oldPkg) {
692             mPermissionManagerServiceImpl.onPackageAdded(packageState, isInstantApp, oldPkg);
693         }
694 
695         @Override
onPackageInstalled(@onNull AndroidPackage pkg, int previousAppId, @NonNull PackageInstalledParams params, @UserIdInt int rawUserId)696         public void onPackageInstalled(@NonNull AndroidPackage pkg, int previousAppId,
697                 @NonNull PackageInstalledParams params, @UserIdInt int rawUserId) {
698             Objects.requireNonNull(pkg, "pkg");
699             Objects.requireNonNull(params, "params");
700             Preconditions.checkArgument(rawUserId >= UserHandle.USER_SYSTEM
701                     || rawUserId == UserHandle.USER_ALL, "userId");
702 
703             mPermissionManagerServiceImpl.onPackageInstalled(pkg, previousAppId, params, rawUserId);
704             final int[] userIds = rawUserId == UserHandle.USER_ALL ? getAllUserIds()
705                     : new int[] { rawUserId };
706             for (final int userId : userIds) {
707                 final int autoRevokePermissionsMode = params.getAutoRevokePermissionsMode();
708                 if (autoRevokePermissionsMode == AppOpsManager.MODE_ALLOWED
709                         || autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED) {
710                     setAutoRevokeExemptedInternal(pkg,
711                             autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED, userId);
712                 }
713             }
714         }
715 
716         @Override
onPackageRemoved(@onNull AndroidPackage pkg)717         public void onPackageRemoved(@NonNull AndroidPackage pkg) {
718             mPermissionManagerServiceImpl.onPackageRemoved(pkg);
719         }
720 
721         @Override
onPackageUninstalled(@onNull String packageName, int appId, @NonNull PackageState packageState, @Nullable AndroidPackage pkg, @NonNull List<AndroidPackage> sharedUserPkgs, @UserIdInt int userId)722         public void onPackageUninstalled(@NonNull String packageName, int appId,
723                 @NonNull PackageState packageState, @Nullable AndroidPackage pkg,
724                 @NonNull List<AndroidPackage> sharedUserPkgs, @UserIdInt int userId) {
725             mPermissionManagerServiceImpl.onPackageUninstalled(packageName, appId, packageState,
726                     pkg, sharedUserPkgs, userId);
727         }
728 
729         @Override
addOnRuntimePermissionStateChangedListener( OnRuntimePermissionStateChangedListener listener)730         public void addOnRuntimePermissionStateChangedListener(
731                 OnRuntimePermissionStateChangedListener listener) {
732             mPermissionManagerServiceImpl.addOnRuntimePermissionStateChangedListener(listener);
733         }
734 
735         @Override
removeOnRuntimePermissionStateChangedListener( OnRuntimePermissionStateChangedListener listener)736         public void removeOnRuntimePermissionStateChangedListener(
737                 OnRuntimePermissionStateChangedListener listener) {
738             mPermissionManagerServiceImpl.removeOnRuntimePermissionStateChangedListener(listener);
739         }
740 
741         @Override
onSystemReady()742         public void onSystemReady() {
743             mPermissionManagerServiceImpl.onSystemReady();
744         }
745 
746         @Override
isPermissionsReviewRequired(@onNull String packageName, @UserIdInt int userId)747         public boolean isPermissionsReviewRequired(@NonNull String packageName,
748                 @UserIdInt int userId) {
749             return mPermissionManagerServiceImpl.isPermissionsReviewRequired(packageName, userId);
750         }
751 
752         @Override
readLegacyPermissionStateTEMP()753         public void readLegacyPermissionStateTEMP() {
754             mPermissionManagerServiceImpl.readLegacyPermissionStateTEMP();
755         }
756         @Override
writeLegacyPermissionStateTEMP()757         public void writeLegacyPermissionStateTEMP() {
758             mPermissionManagerServiceImpl.writeLegacyPermissionStateTEMP();
759         }
760         @Override
onUserRemoved(@serIdInt int userId)761         public void onUserRemoved(@UserIdInt int userId) {
762             mPermissionManagerServiceImpl.onUserRemoved(userId);
763         }
764         @NonNull
765         @Override
getInstalledPermissions(@onNull String packageName)766         public Set<String> getInstalledPermissions(@NonNull String packageName) {
767             return mPermissionManagerServiceImpl.getInstalledPermissions(packageName);
768         }
769         @NonNull
770         @Override
getGrantedPermissions(@onNull String packageName, @UserIdInt int userId)771         public Set<String> getGrantedPermissions(@NonNull String packageName,
772                 @UserIdInt int userId) {
773             return mPermissionManagerServiceImpl.getGrantedPermissions(packageName, userId);
774         }
775         @NonNull
776         @Override
getPermissionGids(@onNull String permissionName, @UserIdInt int userId)777         public int[] getPermissionGids(@NonNull String permissionName, @UserIdInt int userId) {
778             return mPermissionManagerServiceImpl.getPermissionGids(permissionName, userId);
779         }
780         @NonNull
781         @Override
getAppOpPermissionPackages(@onNull String permissionName)782         public String[] getAppOpPermissionPackages(@NonNull String permissionName) {
783             return mPermissionManagerServiceImpl.getAppOpPermissionPackages(permissionName);
784         }
785         @Override
onStorageVolumeMounted(@ullable String volumeUuid, boolean fingerprintChanged)786         public void onStorageVolumeMounted(@Nullable String volumeUuid,
787                 boolean fingerprintChanged) {
788             mPermissionManagerServiceImpl.onStorageVolumeMounted(volumeUuid, fingerprintChanged);
789         }
790         @Override
resetRuntimePermissions(@onNull AndroidPackage pkg, @UserIdInt int userId)791         public void resetRuntimePermissions(@NonNull AndroidPackage pkg, @UserIdInt int userId) {
792             mPermissionManagerServiceImpl.resetRuntimePermissions(pkg, userId);
793         }
794         @Override
resetRuntimePermissionsForUser(@serIdInt int userId)795         public void resetRuntimePermissionsForUser(@UserIdInt int userId) {
796             mPermissionManagerServiceImpl.resetRuntimePermissionsForUser(userId);
797         }
798 
799         @Override
getPermissionTEMP(String permName)800         public Permission getPermissionTEMP(String permName) {
801             return mPermissionManagerServiceImpl.getPermissionTEMP(permName);
802         }
803 
804         @NonNull
805         @Override
getAllPermissionsWithProtection( @ermissionInfo.Protection int protection)806         public List<PermissionInfo> getAllPermissionsWithProtection(
807                 @PermissionInfo.Protection int protection) {
808             return mPermissionManagerServiceImpl.getAllPermissionsWithProtection(protection);
809         }
810 
811         @NonNull
812         @Override
getAllPermissionsWithProtectionFlags( @ermissionInfo.ProtectionFlags int protectionFlags)813         public List<PermissionInfo> getAllPermissionsWithProtectionFlags(
814                 @PermissionInfo.ProtectionFlags int protectionFlags) {
815             return mPermissionManagerServiceImpl
816                     .getAllPermissionsWithProtectionFlags(protectionFlags);
817         }
818 
819         /* End of delegate methods to PermissionManagerServiceInterface */
820     }
821 
822     /**
823      * Returns all relevant user ids.  This list include the current set of created user ids as well
824      * as pre-created user ids.
825      * @return user ids for created users and pre-created users
826      */
getAllUserIds()827     private int[] getAllUserIds() {
828         return UserManagerService.getInstance().getUserIdsIncludingPreCreated();
829     }
830 
831     /**
832      * Interface to intercept permission checks and optionally pass through to the original
833      * implementation.
834      */
835     private interface CheckPermissionDelegate {
836         /**
837          * Get the UID whose permission checks is being delegated.
838          *
839          * @return the UID
840          */
getDelegatedUid()841         int getDelegatedUid();
842 
843         /**
844          * Check whether the given package has been granted the specified permission.
845          *
846          * @param packageName the name of the package to be checked
847          * @param permissionName the name of the permission to be checked
848          * @param userId the user ID
849          * @param superImpl the original implementation that can be delegated to
850          * @return {@link android.content.pm.PackageManager#PERMISSION_GRANTED} if the package has
851          * the permission, or {@link android.content.pm.PackageManager#PERMISSION_DENIED} otherwise
852          *
853          * @see android.content.pm.PackageManager#checkPermission(String, String)
854          */
checkPermission(@onNull String packageName, @NonNull String permissionName, @UserIdInt int userId, @NonNull TriFunction<String, String, Integer, Integer> superImpl)855         int checkPermission(@NonNull String packageName, @NonNull String permissionName,
856                 @UserIdInt int userId,
857                 @NonNull TriFunction<String, String, Integer, Integer> superImpl);
858 
859         /**
860          * Check whether the given UID has been granted the specified permission.
861          *
862          * @param uid the UID to be checked
863          * @param permissionName the name of the permission to be checked
864          * @param superImpl the original implementation that can be delegated to
865          * @return {@link android.content.pm.PackageManager#PERMISSION_GRANTED} if the package has
866          * the permission, or {@link android.content.pm.PackageManager#PERMISSION_DENIED} otherwise
867          */
checkUidPermission(int uid, @NonNull String permissionName, BiFunction<Integer, String, Integer> superImpl)868         int checkUidPermission(int uid, @NonNull String permissionName,
869                 BiFunction<Integer, String, Integer> superImpl);
870 
871         /**
872          * @return list of delegated permissions
873          */
getDelegatedPermissionNames()874         List<String> getDelegatedPermissionNames();
875     }
876 
877     private class ShellDelegate implements CheckPermissionDelegate {
878         private final int mDelegatedUid;
879         @NonNull
880         private final String mDelegatedPackageName;
881         @Nullable
882         private final List<String> mDelegatedPermissionNames;
883 
ShellDelegate(int delegatedUid, @NonNull String delegatedPackageName, @Nullable List<String> delegatedPermissionNames)884         public ShellDelegate(int delegatedUid, @NonNull String delegatedPackageName,
885                 @Nullable List<String> delegatedPermissionNames) {
886             mDelegatedUid = delegatedUid;
887             mDelegatedPackageName = delegatedPackageName;
888             mDelegatedPermissionNames = delegatedPermissionNames;
889         }
890 
891         @Override
getDelegatedUid()892         public int getDelegatedUid() {
893             return mDelegatedUid;
894         }
895 
896         @Override
checkPermission(@onNull String packageName, @NonNull String permissionName, int userId, @NonNull TriFunction<String, String, Integer, Integer> superImpl)897         public int checkPermission(@NonNull String packageName, @NonNull String permissionName,
898                 int userId, @NonNull TriFunction<String, String, Integer, Integer> superImpl) {
899             if (mDelegatedPackageName.equals(packageName)
900                     && isDelegatedPermission(permissionName)) {
901                 final long identity = Binder.clearCallingIdentity();
902                 try {
903                     return superImpl.apply("com.android.shell", permissionName, userId);
904                 } finally {
905                     Binder.restoreCallingIdentity(identity);
906                 }
907             }
908             return superImpl.apply(packageName, permissionName, userId);
909         }
910 
911         @Override
checkUidPermission(int uid, @NonNull String permissionName, @NonNull BiFunction<Integer, String, Integer> superImpl)912         public int checkUidPermission(int uid, @NonNull String permissionName,
913                 @NonNull BiFunction<Integer, String, Integer> superImpl) {
914             if (uid == mDelegatedUid && isDelegatedPermission(permissionName)) {
915                 final long identity = Binder.clearCallingIdentity();
916                 try {
917                     return superImpl.apply(Process.SHELL_UID, permissionName);
918                 } finally {
919                     Binder.restoreCallingIdentity(identity);
920                 }
921             }
922             return superImpl.apply(uid, permissionName);
923         }
924 
925         @Override
getDelegatedPermissionNames()926         public List<String> getDelegatedPermissionNames() {
927             return mDelegatedPermissionNames == null
928                     ? null
929                     : new ArrayList<>(mDelegatedPermissionNames);
930         }
931 
isDelegatedPermission(@onNull String permissionName)932         private boolean isDelegatedPermission(@NonNull String permissionName) {
933             // null permissions means all permissions are targeted
934             return mDelegatedPermissionNames == null
935                     || mDelegatedPermissionNames.contains(permissionName);
936         }
937     }
938 
939     private static final class AttributionSourceRegistry {
940         private final Object mLock = new Object();
941 
942         private final Context mContext;
943 
AttributionSourceRegistry(@onNull Context context)944         AttributionSourceRegistry(@NonNull Context context) {
945             mContext = context;
946         }
947 
948         private final WeakHashMap<IBinder, AttributionSource> mAttributions = new WeakHashMap<>();
949 
registerAttributionSource(@onNull AttributionSource source)950         public void registerAttributionSource(@NonNull AttributionSource source) {
951             //   Here we keep track of attribution sources that were created by an app
952             // from an attribution chain that called into the app and the apps's
953             // own attribution source. An app can register an attribution chain up
954             // to itself inclusive if and only if it is adding a node for itself which
955             // optionally points to an attribution chain that was created by each
956             // preceding app recursively up to the beginning of the chain.
957             //   The only special case is when the first app in the attribution chain
958             // creates a source that points to another app (not a chain of apps). We
959             // allow this even if the source the app points to is not registered since
960             // in app ops we allow every app to blame every other app (untrusted if not
961             // holding a special permission).
962             //  This technique ensures that a bad actor in the middle of the attribution
963             // chain can neither prepend nor append an invalid attribution sequence, i.e.
964             // a sequence that is not constructed by trusted sources up to the that bad
965             // actor's app.
966             //   Note that passing your attribution source to another app means you allow
967             // it to blame private data access on your app. This can be mediated by the OS
968             // in, which case security is already enforced; by other app's code running in
969             // your process calling into the other app, in which case it can already access
970             // the private data in your process; or by you explicitly calling to another
971             // app passing the source, in which case you must trust the other side;
972 
973             final int callingUid = resolveUid(Binder.getCallingUid());
974             final int sourceUid = resolveUid(source.getUid());
975             if (sourceUid != callingUid && mContext.checkPermission(
976                     Manifest.permission.UPDATE_APP_OPS_STATS, /*pid*/ -1, callingUid)
977                     != PackageManager.PERMISSION_GRANTED) {
978                 throw new SecurityException("Cannot register attribution source for uid:"
979                         + sourceUid + " from uid:" + callingUid);
980             }
981 
982             final PackageManagerInternal packageManagerInternal = LocalServices.getService(
983                     PackageManagerInternal.class);
984 
985             // TODO(b/234653108): Clean up this UID/package & cross-user check.
986             // If calling from the system process, allow registering attribution for package from
987             // any user
988             int userId = UserHandle.getUserId((callingUid == Process.SYSTEM_UID ? sourceUid
989                     : callingUid));
990             if (packageManagerInternal.getPackageUid(source.getPackageName(), 0, userId)
991                     != sourceUid) {
992                 throw new SecurityException("Cannot register attribution source for package:"
993                         + source.getPackageName() + " from uid:" + callingUid);
994             }
995 
996             final AttributionSource next = source.getNext();
997             if (next != null && next.getNext() != null
998                     && !isRegisteredAttributionSource(next)) {
999                 throw new SecurityException("Cannot register forged attribution source:"
1000                         + source);
1001             }
1002 
1003             synchronized (mLock) {
1004                 // Change the token for the AttributionSource we're storing, so that we don't store
1005                 // a strong reference to the original token inside the map itself.
1006                 mAttributions.put(source.getToken(), source.withDefaultToken());
1007             }
1008         }
1009 
isRegisteredAttributionSource(@onNull AttributionSource source)1010         public boolean isRegisteredAttributionSource(@NonNull AttributionSource source) {
1011             synchronized (mLock) {
1012                 final AttributionSource cachedSource = mAttributions.get(source.getToken());
1013                 if (cachedSource != null) {
1014                     return cachedSource.equalsExceptToken(source);
1015                 }
1016                 return false;
1017             }
1018         }
1019 
resolveUid(int uid)1020         private int resolveUid(int uid) {
1021             final VoiceInteractionManagerInternal vimi = LocalServices
1022                     .getService(VoiceInteractionManagerInternal.class);
1023             if (vimi == null) {
1024                 return uid;
1025             }
1026             final VoiceInteractionManagerInternal.HotwordDetectionServiceIdentity
1027                     hotwordDetectionServiceIdentity = vimi.getHotwordDetectionServiceIdentity();
1028             if (hotwordDetectionServiceIdentity != null
1029                     && uid == hotwordDetectionServiceIdentity.getIsolatedUid()) {
1030                 return hotwordDetectionServiceIdentity.getOwnerUid();
1031             }
1032             return uid;
1033         }
1034     }
1035 
1036     /**
1037      * TODO: We need to consolidate these APIs either on PermissionManager or an extension
1038      * object or a separate PermissionChecker service in context. The impartant part is to
1039      * keep a single impl that is exposed to Java and native. We are not sure about the
1040      * API shape so let is soak a bit.
1041      */
1042     private static final class PermissionCheckerService extends IPermissionChecker.Stub {
1043         // Cache for platform defined runtime permissions to avoid multi lookup (name -> info)
1044         private static final ConcurrentHashMap<String, PermissionInfo> sPlatformPermissions
1045                 = new ConcurrentHashMap<>();
1046 
1047         private static final AtomicInteger sAttributionChainIds = new AtomicInteger(0);
1048 
1049         private final @NonNull Context mContext;
1050         private final @NonNull AppOpsManager mAppOpsManager;
1051         private final @NonNull PermissionManagerServiceInternal mPermissionManagerServiceInternal;
1052 
PermissionCheckerService(@onNull Context context)1053         PermissionCheckerService(@NonNull Context context) {
1054             mContext = context;
1055             mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
1056             mPermissionManagerServiceInternal =
1057                     LocalServices.getService(PermissionManagerServiceInternal.class);
1058         }
1059 
1060         @Override
1061         @PermissionCheckerManager.PermissionResult
checkPermission(@onNull String permission, @NonNull AttributionSourceState attributionSourceState, @Nullable String message, boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource, int attributedOp)1062         public int checkPermission(@NonNull String permission,
1063                 @NonNull AttributionSourceState attributionSourceState, @Nullable String message,
1064                 boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource,
1065                 int attributedOp) {
1066             Objects.requireNonNull(permission);
1067             Objects.requireNonNull(attributionSourceState);
1068             final AttributionSource attributionSource = new AttributionSource(
1069                     attributionSourceState);
1070             final int result = checkPermission(mContext, mPermissionManagerServiceInternal,
1071                     permission, attributionSource, message, forDataDelivery, startDataDelivery,
1072                     fromDatasource, attributedOp);
1073             // Finish any started op if some step in the attribution chain failed.
1074             if (startDataDelivery && result != PermissionChecker.PERMISSION_GRANTED
1075                     && result != PermissionChecker.PERMISSION_SOFT_DENIED) {
1076                 if (attributedOp == AppOpsManager.OP_NONE) {
1077                     finishDataDelivery(AppOpsManager.permissionToOpCode(permission),
1078                             attributionSource.asState(), fromDatasource);
1079                 } else {
1080                     finishDataDelivery(attributedOp, attributionSource.asState(), fromDatasource);
1081                 }
1082             }
1083             return result;
1084         }
1085 
1086         @Override
finishDataDelivery(int op, @NonNull AttributionSourceState attributionSourceState, boolean fromDataSource)1087         public void finishDataDelivery(int op,
1088                 @NonNull AttributionSourceState attributionSourceState, boolean fromDataSource) {
1089             finishDataDelivery(mContext, op, attributionSourceState,
1090                     fromDataSource);
1091         }
1092 
finishDataDelivery(Context context, int op, @NonNull AttributionSourceState attributionSourceState, boolean fromDatasource)1093         private static void finishDataDelivery(Context context, int op,
1094                 @NonNull AttributionSourceState attributionSourceState, boolean fromDatasource) {
1095             Objects.requireNonNull(attributionSourceState);
1096             AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
1097 
1098             if (op == AppOpsManager.OP_NONE) {
1099                 return;
1100             }
1101 
1102             AttributionSource current = new AttributionSource(attributionSourceState);
1103             AttributionSource next = null;
1104 
1105             while (true) {
1106                 final boolean skipCurrentFinish = (fromDatasource || next != null);
1107 
1108                 next = current.getNext();
1109 
1110                 // If the call is from a datasource we need to vet only the chain before it. This
1111                 // way we can avoid the datasource creating an attribution context for every call.
1112                 if (!(fromDatasource && current.asState() == attributionSourceState)
1113                         && next != null && !current.isTrusted(context)) {
1114                     return;
1115                 }
1116 
1117                 // The access is for oneself if this is the single receiver of data
1118                 // after the data source or if this is the single attribution source
1119                 // in the chain if not from a datasource.
1120                 final boolean singleReceiverFromDatasource = (fromDatasource
1121                         && current.asState() == attributionSourceState && next != null
1122                         && next.getNext() == null);
1123                 final boolean selfAccess = singleReceiverFromDatasource || next == null;
1124 
1125                 final AttributionSource accessorSource = (!singleReceiverFromDatasource)
1126                         ? current : next;
1127 
1128                 if (selfAccess) {
1129                     final String resolvedPackageName = resolvePackageName(context, accessorSource);
1130                     if (resolvedPackageName == null) {
1131                         return;
1132                     }
1133                     appOpsManager.finishOp(attributionSourceState.token, op,
1134                             accessorSource.getUid(), resolvedPackageName,
1135                             accessorSource.getAttributionTag());
1136                 } else {
1137                     final AttributionSource resolvedAttributionSource =
1138                             resolveAttributionSource(context, accessorSource);
1139                     if (resolvedAttributionSource.getPackageName() == null) {
1140                         return;
1141                     }
1142                     appOpsManager.finishProxyOp(attributionSourceState.token,
1143                             AppOpsManager.opToPublicName(op), resolvedAttributionSource,
1144                             skipCurrentFinish);
1145                 }
1146                 RegisteredAttribution registered =
1147                         sRunningAttributionSources.remove(current.getToken());
1148                 if (registered != null) {
1149                     registered.unregister();
1150                 }
1151 
1152                 if (next == null || next.getNext() == null) {
1153                     if (next != null) {
1154                         registered = sRunningAttributionSources.remove(next.getToken());
1155                         if (registered != null) {
1156                             registered.unregister();
1157                         }
1158                     }
1159                     return;
1160                 }
1161                 current = next;
1162             }
1163         }
1164 
1165         @Override
1166         @PermissionCheckerManager.PermissionResult
checkOp(int op, AttributionSourceState attributionSource, String message, boolean forDataDelivery, boolean startDataDelivery)1167         public int checkOp(int op, AttributionSourceState attributionSource,
1168                 String message, boolean forDataDelivery, boolean startDataDelivery) {
1169             int result = checkOp(mContext, op, mPermissionManagerServiceInternal,
1170                     new AttributionSource(attributionSource), message, forDataDelivery,
1171                     startDataDelivery);
1172             if (result != PermissionChecker.PERMISSION_GRANTED && startDataDelivery) {
1173                 // Finish any started op if some step in the attribution chain failed.
1174                 finishDataDelivery(op, attributionSource, /*fromDatasource*/ false);
1175             }
1176             return result;
1177         }
1178 
1179         @PermissionCheckerManager.PermissionResult
checkPermission(@onNull Context context, @NonNull PermissionManagerServiceInternal permissionManagerServiceInt, @NonNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message, boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource, int attributedOp)1180         private static int checkPermission(@NonNull Context context,
1181                 @NonNull PermissionManagerServiceInternal permissionManagerServiceInt,
1182                 @NonNull String permission, @NonNull AttributionSource attributionSource,
1183                 @Nullable String message, boolean forDataDelivery, boolean startDataDelivery,
1184                 boolean fromDatasource, int attributedOp) {
1185             PermissionInfo permissionInfo = sPlatformPermissions.get(permission);
1186 
1187             if (permissionInfo == null) {
1188                 try {
1189                     permissionInfo = context.getPackageManager().getPermissionInfo(permission, 0);
1190                     if (PLATFORM_PACKAGE_NAME.equals(permissionInfo.packageName)
1191                             || HealthConnectManager.isHealthPermission(context, permission)) {
1192                         // Double addition due to concurrency is fine - the backing
1193                         // store is concurrent.
1194                         sPlatformPermissions.put(permission, permissionInfo);
1195                     }
1196                 } catch (PackageManager.NameNotFoundException ignored) {
1197                     return PermissionChecker.PERMISSION_HARD_DENIED;
1198                 }
1199             }
1200 
1201             if (permissionInfo.isAppOp()) {
1202                 return checkAppOpPermission(context, permissionManagerServiceInt, permission,
1203                         attributionSource, message, forDataDelivery, fromDatasource);
1204             }
1205             if (permissionInfo.isRuntime()) {
1206                 return checkRuntimePermission(context, permissionManagerServiceInt, permission,
1207                         attributionSource, message, forDataDelivery, startDataDelivery,
1208                         fromDatasource, attributedOp);
1209             }
1210 
1211             if (!fromDatasource && !checkPermission(context, permissionManagerServiceInt,
1212                     permission, attributionSource.getUid(),
1213                     attributionSource.getRenouncedPermissions())) {
1214                 return PermissionChecker.PERMISSION_HARD_DENIED;
1215             }
1216 
1217             if (attributionSource.getNext() != null) {
1218                 return checkPermission(context, permissionManagerServiceInt, permission,
1219                         attributionSource.getNext(), message, forDataDelivery, startDataDelivery,
1220                         /*fromDatasource*/ false, attributedOp);
1221             }
1222 
1223             return PermissionChecker.PERMISSION_GRANTED;
1224         }
1225 
1226         @PermissionCheckerManager.PermissionResult
checkAppOpPermission(@onNull Context context, @NonNull PermissionManagerServiceInternal permissionManagerServiceInt, @NonNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message, boolean forDataDelivery, boolean fromDatasource)1227         private static int checkAppOpPermission(@NonNull Context context,
1228                 @NonNull PermissionManagerServiceInternal permissionManagerServiceInt,
1229                 @NonNull String permission, @NonNull AttributionSource attributionSource,
1230                 @Nullable String message, boolean forDataDelivery, boolean fromDatasource) {
1231             final int op = AppOpsManager.permissionToOpCode(permission);
1232             if (op < 0) {
1233                 Slog.wtf(LOG_TAG, "Appop permission " + permission + " with no app op defined!");
1234                 return PermissionChecker.PERMISSION_HARD_DENIED;
1235             }
1236 
1237             AttributionSource current = attributionSource;
1238             AttributionSource next = null;
1239 
1240             while (true) {
1241                 final boolean skipCurrentChecks = (fromDatasource || next != null);
1242 
1243                 next = current.getNext();
1244 
1245                 // If the call is from a datasource we need to vet only the chain before it. This
1246                 // way we can avoid the datasource creating an attribution context for every call.
1247                 if (!(fromDatasource && current.equals(attributionSource))
1248                         && next != null && !current.isTrusted(context)) {
1249                     return PermissionChecker.PERMISSION_HARD_DENIED;
1250                 }
1251 
1252                 // The access is for oneself if this is the single receiver of data
1253                 // after the data source or if this is the single attribution source
1254                 // in the chain if not from a datasource.
1255                 final boolean singleReceiverFromDatasource = (fromDatasource
1256                         && current.equals(attributionSource) && next != null
1257                         && next.getNext() == null);
1258                 final boolean selfAccess = singleReceiverFromDatasource || next == null;
1259 
1260                 final int opMode = performOpTransaction(context, attributionSource.getToken(), op,
1261                         current, message, forDataDelivery, /*startDataDelivery*/ false,
1262                         skipCurrentChecks, selfAccess, singleReceiverFromDatasource,
1263                         AppOpsManager.OP_NONE, AppOpsManager.ATTRIBUTION_FLAGS_NONE,
1264                         AppOpsManager.ATTRIBUTION_FLAGS_NONE,
1265                         AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE);
1266 
1267                 switch (opMode) {
1268                     case AppOpsManager.MODE_IGNORED:
1269                     case AppOpsManager.MODE_ERRORED: {
1270                         return PermissionChecker.PERMISSION_HARD_DENIED;
1271                     }
1272                     case AppOpsManager.MODE_DEFAULT: {
1273                         if (!skipCurrentChecks && !checkPermission(context,
1274                                 permissionManagerServiceInt, permission, attributionSource.getUid(),
1275                                 attributionSource.getRenouncedPermissions())) {
1276                             return PermissionChecker.PERMISSION_HARD_DENIED;
1277                         }
1278                         if (next != null && !checkPermission(context, permissionManagerServiceInt,
1279                                 permission, next.getUid(), next.getRenouncedPermissions())) {
1280                             return PermissionChecker.PERMISSION_HARD_DENIED;
1281                         }
1282                     }
1283                 }
1284 
1285                 if (next == null || next.getNext() == null) {
1286                     return PermissionChecker.PERMISSION_GRANTED;
1287                 }
1288 
1289                 current = next;
1290             }
1291         }
1292 
checkRuntimePermission(@onNull Context context, @NonNull PermissionManagerServiceInternal permissionManagerServiceInt, @NonNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message, boolean forDataDelivery, boolean startDataDelivery, boolean fromDatasource, int attributedOp)1293         private static int checkRuntimePermission(@NonNull Context context,
1294                 @NonNull PermissionManagerServiceInternal permissionManagerServiceInt,
1295                 @NonNull String permission, @NonNull AttributionSource attributionSource,
1296                 @Nullable String message, boolean forDataDelivery, boolean startDataDelivery,
1297                 boolean fromDatasource, int attributedOp) {
1298             // Now let's check the identity chain...
1299             final int op = AppOpsManager.permissionToOpCode(permission);
1300             final int attributionChainId =
1301                     getAttributionChainId(startDataDelivery, attributionSource);
1302             final boolean hasChain = attributionChainId != ATTRIBUTION_CHAIN_ID_NONE;
1303             AttributionSource current = attributionSource;
1304             AttributionSource next = null;
1305             // We consider the chain trusted if the start node has UPDATE_APP_OPS_STATS, and
1306             // every attributionSource in the chain is registered with the system.
1307             final boolean isChainStartTrusted = !hasChain || checkPermission(context,
1308                     permissionManagerServiceInt, UPDATE_APP_OPS_STATS, current.getUid(),
1309                     current.getRenouncedPermissions());
1310 
1311             while (true) {
1312                 final boolean skipCurrentChecks = (fromDatasource || next != null);
1313                 next = current.getNext();
1314 
1315                 // If the call is from a datasource we need to vet only the chain before it. This
1316                 // way we can avoid the datasource creating an attribution context for every call.
1317                 if (!(fromDatasource && current.equals(attributionSource))
1318                         && next != null && !current.isTrusted(context)) {
1319                     return PermissionChecker.PERMISSION_HARD_DENIED;
1320                 }
1321 
1322                 // If we already checked the permission for this one, skip the work
1323                 if (!skipCurrentChecks && !checkPermission(context, permissionManagerServiceInt,
1324                         permission, current.getUid(), current.getRenouncedPermissions())) {
1325                     return PermissionChecker.PERMISSION_HARD_DENIED;
1326                 }
1327 
1328                 if (next != null && !checkPermission(context, permissionManagerServiceInt,
1329                         permission, next.getUid(), next.getRenouncedPermissions())) {
1330                     return PermissionChecker.PERMISSION_HARD_DENIED;
1331                 }
1332 
1333                 if (op < 0) {
1334                     // Bg location is one-off runtime modifier permission and has no app op
1335                     if (sPlatformPermissions.containsKey(permission)
1336                             && !Manifest.permission.ACCESS_BACKGROUND_LOCATION.equals(permission)
1337                             && !Manifest.permission.BODY_SENSORS_BACKGROUND.equals(permission)) {
1338                         Slog.wtf(LOG_TAG, "Platform runtime permission " + permission
1339                                 + " with no app op defined!");
1340                     }
1341                     if (next == null) {
1342                         return PermissionChecker.PERMISSION_GRANTED;
1343                     }
1344                     current = next;
1345                     continue;
1346                 }
1347 
1348                 // The access is for oneself if this is the single receiver of data
1349                 // after the data source or if this is the single attribution source
1350                 // in the chain if not from a datasource.
1351                 final boolean singleReceiverFromDatasource = (fromDatasource
1352                         && current.equals(attributionSource)
1353                         && next != null && next.getNext() == null);
1354                 final boolean selfAccess = singleReceiverFromDatasource || next == null;
1355                 final boolean isLinkTrusted = isChainStartTrusted
1356                         && (current.isTrusted(context) || current.equals(attributionSource))
1357                         && (next == null || next.isTrusted(context));
1358 
1359                 final int proxyAttributionFlags = (!skipCurrentChecks && hasChain)
1360                         ? resolveProxyAttributionFlags(attributionSource, current, fromDatasource,
1361                                 startDataDelivery, selfAccess, isLinkTrusted)
1362                         : ATTRIBUTION_FLAGS_NONE;
1363                 final int proxiedAttributionFlags = hasChain ? resolveProxiedAttributionFlags(
1364                         attributionSource, next, fromDatasource, startDataDelivery, selfAccess,
1365                         isLinkTrusted) : ATTRIBUTION_FLAGS_NONE;
1366 
1367                 final int opMode = performOpTransaction(context, attributionSource.getToken(), op,
1368                         current, message, forDataDelivery, startDataDelivery, skipCurrentChecks,
1369                         selfAccess, singleReceiverFromDatasource, attributedOp,
1370                         proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
1371 
1372                 switch (opMode) {
1373                     case AppOpsManager.MODE_ERRORED: {
1374                         return PermissionChecker.PERMISSION_HARD_DENIED;
1375                     }
1376                     case AppOpsManager.MODE_IGNORED: {
1377                         return PermissionChecker.PERMISSION_SOFT_DENIED;
1378                     }
1379                 }
1380 
1381                 if (startDataDelivery) {
1382                     RegisteredAttribution registered = new RegisteredAttribution(context, op,
1383                             current, fromDatasource);
1384                     sRunningAttributionSources.put(current.getToken(), registered);
1385                 }
1386 
1387                 if (next == null || next.getNext() == null) {
1388                     return PermissionChecker.PERMISSION_GRANTED;
1389                 }
1390 
1391                 current = next;
1392             }
1393         }
1394 
checkPermission(@onNull Context context, @NonNull PermissionManagerServiceInternal permissionManagerServiceInt, @NonNull String permission, int uid, @NonNull Set<String> renouncedPermissions)1395         private static boolean checkPermission(@NonNull Context context,
1396                 @NonNull PermissionManagerServiceInternal permissionManagerServiceInt,
1397                 @NonNull String permission, int uid, @NonNull Set<String> renouncedPermissions) {
1398             boolean permissionGranted = context.checkPermission(permission, /*pid*/ -1,
1399                     uid) == PackageManager.PERMISSION_GRANTED;
1400 
1401             // Override certain permissions checks for the shared isolated process for both
1402             // HotwordDetectionService and VisualQueryDetectionService, which ordinarily cannot hold
1403             // any permissions.
1404             // There's probably a cleaner, more generalizable way to do this. For now, this is
1405             // the only use case for this, so simply override here.
1406             if (!permissionGranted
1407                     && Process.isIsolated(uid) // simple check which fails-fast for the common case
1408                     && (permission.equals(RECORD_AUDIO) || permission.equals(CAPTURE_AUDIO_HOTWORD)
1409                     || permission.equals(CAPTURE_AUDIO_OUTPUT) || permission.equals(CAMERA))) {
1410                 HotwordDetectionServiceProvider hotwordServiceProvider =
1411                         permissionManagerServiceInt.getHotwordDetectionServiceProvider();
1412                 permissionGranted = hotwordServiceProvider != null
1413                         && uid == hotwordServiceProvider.getUid();
1414             }
1415 
1416             if (permissionGranted && renouncedPermissions.contains(permission)
1417                     && context.checkPermission(Manifest.permission.RENOUNCE_PERMISSIONS,
1418                     /*pid*/ -1, uid) == PackageManager.PERMISSION_GRANTED) {
1419                 return false;
1420             }
1421             return permissionGranted;
1422         }
1423 
resolveProxyAttributionFlags( @onNull AttributionSource attributionChain, @NonNull AttributionSource current, boolean fromDatasource, boolean startDataDelivery, boolean selfAccess, boolean isTrusted)1424         private static @AttributionFlags int resolveProxyAttributionFlags(
1425                 @NonNull AttributionSource attributionChain,
1426                 @NonNull AttributionSource current, boolean fromDatasource,
1427                 boolean startDataDelivery, boolean selfAccess, boolean isTrusted) {
1428             return resolveAttributionFlags(attributionChain, current, fromDatasource,
1429                     startDataDelivery, selfAccess, isTrusted, /*flagsForProxy*/ true);
1430         }
1431 
resolveProxiedAttributionFlags( @onNull AttributionSource attributionChain, @NonNull AttributionSource current, boolean fromDatasource, boolean startDataDelivery, boolean selfAccess, boolean isTrusted)1432         private static @AttributionFlags int resolveProxiedAttributionFlags(
1433                 @NonNull AttributionSource attributionChain,
1434                 @NonNull AttributionSource current, boolean fromDatasource,
1435                 boolean startDataDelivery, boolean selfAccess, boolean isTrusted) {
1436             return resolveAttributionFlags(attributionChain, current, fromDatasource,
1437                     startDataDelivery, selfAccess, isTrusted, /*flagsForProxy*/ false);
1438         }
1439 
resolveAttributionFlags( @onNull AttributionSource attributionChain, @NonNull AttributionSource current, boolean fromDatasource, boolean startDataDelivery, boolean selfAccess, boolean isTrusted, boolean flagsForProxy)1440         private static @AttributionFlags int resolveAttributionFlags(
1441                 @NonNull AttributionSource attributionChain,
1442                 @NonNull AttributionSource current, boolean fromDatasource,
1443                 boolean startDataDelivery, boolean selfAccess, boolean isTrusted,
1444                 boolean flagsForProxy) {
1445             if (current == null || !startDataDelivery) {
1446                 return AppOpsManager.ATTRIBUTION_FLAGS_NONE;
1447             }
1448             int trustedFlag = isTrusted
1449                     ? AppOpsManager.ATTRIBUTION_FLAG_TRUSTED : AppOpsManager.ATTRIBUTION_FLAGS_NONE;
1450             if (flagsForProxy) {
1451                 if (selfAccess) {
1452                     return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR;
1453                 } else if (!fromDatasource && current.equals(attributionChain)) {
1454                     return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR;
1455                 }
1456             } else {
1457                 if (selfAccess) {
1458                     return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_RECEIVER;
1459                 } else if (fromDatasource && current.equals(attributionChain.getNext())) {
1460                     return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR;
1461                 } else if (current.getNext() == null) {
1462                     return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_RECEIVER;
1463                 }
1464             }
1465             if (fromDatasource && current.equals(attributionChain)) {
1466                 return AppOpsManager.ATTRIBUTION_FLAGS_NONE;
1467             }
1468             return trustedFlag | AppOpsManager.ATTRIBUTION_FLAG_INTERMEDIARY;
1469         }
1470 
checkOp(@onNull Context context, @NonNull int op, @NonNull PermissionManagerServiceInternal permissionManagerServiceInt, @NonNull AttributionSource attributionSource, @Nullable String message, boolean forDataDelivery, boolean startDataDelivery)1471         private static int checkOp(@NonNull Context context, @NonNull int op,
1472                 @NonNull PermissionManagerServiceInternal permissionManagerServiceInt,
1473                 @NonNull AttributionSource attributionSource, @Nullable String message,
1474                 boolean forDataDelivery, boolean startDataDelivery) {
1475             if (op < 0 || attributionSource.getPackageName() == null) {
1476                 return PermissionChecker.PERMISSION_HARD_DENIED;
1477             }
1478 
1479             final int attributionChainId =
1480                     getAttributionChainId(startDataDelivery, attributionSource);
1481             final boolean hasChain = attributionChainId != ATTRIBUTION_CHAIN_ID_NONE;
1482 
1483             AttributionSource current = attributionSource;
1484             AttributionSource next = null;
1485 
1486             // We consider the chain trusted if the start node has UPDATE_APP_OPS_STATS, and
1487             // every attributionSource in the chain is registered with the system.
1488             final boolean isChainStartTrusted = !hasChain || checkPermission(context,
1489                     permissionManagerServiceInt, UPDATE_APP_OPS_STATS, current.getUid(),
1490                     current.getRenouncedPermissions());
1491 
1492             while (true) {
1493                 final boolean skipCurrentChecks = (next != null);
1494                 next = current.getNext();
1495 
1496                 // If the call is from a datasource we need to vet only the chain before it. This
1497                 // way we can avoid the datasource creating an attribution context for every call.
1498                 if (next != null && !current.isTrusted(context)) {
1499                     return PermissionChecker.PERMISSION_HARD_DENIED;
1500                 }
1501 
1502                 // The access is for oneself if this is the single attribution source in the chain.
1503                 final boolean selfAccess = (next == null);
1504                 final boolean isLinkTrusted = isChainStartTrusted
1505                         && (current.isTrusted(context) || current.equals(attributionSource))
1506                         && (next == null || next.isTrusted(context));
1507 
1508                 final int proxyAttributionFlags = (!skipCurrentChecks && hasChain)
1509                         ? resolveProxyAttributionFlags(attributionSource, current,
1510                                 /*fromDatasource*/ false, startDataDelivery, selfAccess,
1511                         isLinkTrusted) : ATTRIBUTION_FLAGS_NONE;
1512                 final int proxiedAttributionFlags = hasChain ? resolveProxiedAttributionFlags(
1513                         attributionSource, next, /*fromDatasource*/ false, startDataDelivery,
1514                         selfAccess, isLinkTrusted) : ATTRIBUTION_FLAGS_NONE;
1515 
1516                 final int opMode = performOpTransaction(context, current.getToken(), op, current,
1517                         message, forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess,
1518                         /*fromDatasource*/ false, AppOpsManager.OP_NONE, proxyAttributionFlags,
1519                         proxiedAttributionFlags, attributionChainId);
1520 
1521                 switch (opMode) {
1522                     case AppOpsManager.MODE_ERRORED: {
1523                         return PermissionChecker.PERMISSION_HARD_DENIED;
1524                     }
1525                     case AppOpsManager.MODE_IGNORED: {
1526                         return PermissionChecker.PERMISSION_SOFT_DENIED;
1527                     }
1528                 }
1529 
1530                 if (next == null || next.getNext() == null) {
1531                     return PermissionChecker.PERMISSION_GRANTED;
1532                 }
1533 
1534                 current = next;
1535             }
1536         }
1537 
1538         @SuppressWarnings("ConstantConditions")
performOpTransaction(@onNull Context context, @NonNull IBinder chainStartToken, int op, @NonNull AttributionSource attributionSource, @Nullable String message, boolean forDataDelivery, boolean startDataDelivery, boolean skipProxyOperation, boolean selfAccess, boolean singleReceiverFromDatasource, int attributedOp, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId)1539         private static int performOpTransaction(@NonNull Context context,
1540                 @NonNull IBinder chainStartToken, int op,
1541                 @NonNull AttributionSource attributionSource, @Nullable String message,
1542                 boolean forDataDelivery, boolean startDataDelivery, boolean skipProxyOperation,
1543                 boolean selfAccess, boolean singleReceiverFromDatasource, int attributedOp,
1544                 @AttributionFlags int proxyAttributionFlags,
1545                 @AttributionFlags int proxiedAttributionFlags, int attributionChainId) {
1546             // We cannot perform app ops transactions without a package name. In all relevant
1547             // places we pass the package name but just in case there is a bug somewhere we
1548             // do a best effort to resolve the package from the UID (pick first without a loss
1549             // of generality - they are in the same security sandbox).
1550             final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
1551             final AttributionSource accessorSource = (!singleReceiverFromDatasource)
1552                     ? attributionSource : attributionSource.getNext();
1553             if (!forDataDelivery) {
1554                 final String resolvedAccessorPackageName = resolvePackageName(context,
1555                         accessorSource);
1556                 if (resolvedAccessorPackageName == null) {
1557                     return AppOpsManager.MODE_ERRORED;
1558                 }
1559                 final int opMode = appOpsManager.unsafeCheckOpRawNoThrow(op,
1560                         accessorSource.getUid(), resolvedAccessorPackageName);
1561                 final AttributionSource next = accessorSource.getNext();
1562                 if (!selfAccess && opMode == AppOpsManager.MODE_ALLOWED && next != null) {
1563                     final String resolvedNextPackageName = resolvePackageName(context, next);
1564                     if (resolvedNextPackageName == null) {
1565                         return AppOpsManager.MODE_ERRORED;
1566                     }
1567                     return appOpsManager.unsafeCheckOpRawNoThrow(op, next.getUid(),
1568                             resolvedNextPackageName);
1569                 }
1570                 return opMode;
1571             } else if (startDataDelivery) {
1572                 final AttributionSource resolvedAttributionSource = resolveAttributionSource(
1573                         context, accessorSource);
1574                 if (resolvedAttributionSource.getPackageName() == null) {
1575                     return AppOpsManager.MODE_ERRORED;
1576                 }
1577                 // If the datasource is not in a trusted platform component then in would not
1578                 // have UPDATE_APP_OPS_STATS and the call below would fail. The problem is that
1579                 // an app is exposing runtime permission protected data but cannot blame others
1580                 // in a trusted way which would not properly show in permission usage UIs.
1581                 // As a fallback we note a proxy op that blames the app and the datasource.
1582                 int startedOp = op;
1583                 int checkedOpResult = MODE_ALLOWED;
1584                 int startedOpResult;
1585 
1586                 // If the datasource wants to attribute to another app op we need to
1587                 // make sure the op for the permission and the attributed ops allow
1588                 // the operation. We return the less permissive of the two and check
1589                 // the permission op while start the attributed op.
1590                 if (attributedOp != AppOpsManager.OP_NONE && attributedOp != op) {
1591                     checkedOpResult = appOpsManager.checkOpNoThrow(op,
1592                             resolvedAttributionSource.getUid(), resolvedAttributionSource
1593                                     .getPackageName());
1594                     if (checkedOpResult == MODE_ERRORED) {
1595                         return checkedOpResult;
1596                     }
1597                     startedOp = attributedOp;
1598                 }
1599                 if (selfAccess) {
1600                     try {
1601                         startedOpResult = appOpsManager.startOpNoThrow(
1602                                 chainStartToken, startedOp,
1603                                 resolvedAttributionSource.getUid(),
1604                                 resolvedAttributionSource.getPackageName(),
1605                                 /*startIfModeDefault*/ false,
1606                                 resolvedAttributionSource.getAttributionTag(),
1607                                 message, proxyAttributionFlags, attributionChainId);
1608                     } catch (SecurityException e) {
1609                         Slog.w(LOG_TAG, "Datasource " + attributionSource + " protecting data with"
1610                                 + " platform defined runtime permission "
1611                                 + AppOpsManager.opToPermission(op) + " while not having "
1612                                 + Manifest.permission.UPDATE_APP_OPS_STATS);
1613                         startedOpResult = appOpsManager.startProxyOpNoThrow(chainStartToken,
1614                                 attributedOp, attributionSource, message, skipProxyOperation,
1615                                 proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
1616                     }
1617                 } else {
1618                     try {
1619                         startedOpResult = appOpsManager.startProxyOpNoThrow(chainStartToken,
1620                                 startedOp, resolvedAttributionSource, message, skipProxyOperation,
1621                                 proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
1622                     } catch (SecurityException e) {
1623                         //TODO 195339480: remove
1624                         String msg = "Security exception for op " + startedOp + " with source "
1625                                 + attributionSource.getUid() + ":"
1626                                 + attributionSource.getPackageName() + ", "
1627                                 + attributionSource.getNextUid() + ":"
1628                                 + attributionSource.getNextPackageName();
1629                         if (attributionSource.getNext() != null) {
1630                             AttributionSource next = attributionSource.getNext();
1631                             msg = msg + ", " + next.getNextPackageName() + ":" + next.getNextUid();
1632                         }
1633                         throw new SecurityException(msg + ":" + e.getMessage());
1634                     }
1635                 }
1636                 return Math.max(checkedOpResult, startedOpResult);
1637             } else {
1638                 final AttributionSource resolvedAttributionSource = resolveAttributionSource(
1639                         context, accessorSource);
1640                 if (resolvedAttributionSource.getPackageName() == null) {
1641                     return AppOpsManager.MODE_ERRORED;
1642                 }
1643                 int notedOp = op;
1644                 int checkedOpResult = MODE_ALLOWED;
1645                 int notedOpResult;
1646 
1647                 // If the datasource wants to attribute to another app op we need to
1648                 // make sure the op for the permission and the attributed ops allow
1649                 // the operation. We return the less permissive of the two and check
1650                 // the permission op while start the attributed op.
1651                 if (attributedOp != AppOpsManager.OP_NONE && attributedOp != op) {
1652                     checkedOpResult = appOpsManager.checkOpNoThrow(op,
1653                             resolvedAttributionSource.getUid(), resolvedAttributionSource
1654                                     .getPackageName());
1655                     if (checkedOpResult == MODE_ERRORED) {
1656                         return checkedOpResult;
1657                     }
1658                     notedOp = attributedOp;
1659                 }
1660                 if (selfAccess) {
1661                     // If the datasource is not in a trusted platform component then in would not
1662                     // have UPDATE_APP_OPS_STATS and the call below would fail. The problem is that
1663                     // an app is exposing runtime permission protected data but cannot blame others
1664                     // in a trusted way which would not properly show in permission usage UIs.
1665                     // As a fallback we note a proxy op that blames the app and the datasource.
1666                     try {
1667                         notedOpResult = appOpsManager.noteOpNoThrow(notedOp,
1668                                 resolvedAttributionSource.getUid(),
1669                                 resolvedAttributionSource.getPackageName(),
1670                                 resolvedAttributionSource.getAttributionTag(),
1671                                 message);
1672                     } catch (SecurityException e) {
1673                         Slog.w(LOG_TAG, "Datasource " + attributionSource + " protecting data with"
1674                                 + " platform defined runtime permission "
1675                                 + AppOpsManager.opToPermission(op) + " while not having "
1676                                 + Manifest.permission.UPDATE_APP_OPS_STATS);
1677                         notedOpResult = appOpsManager.noteProxyOpNoThrow(notedOp, attributionSource,
1678                                 message, skipProxyOperation);
1679                     }
1680                 } else {
1681                     try {
1682                         notedOpResult = appOpsManager.noteProxyOpNoThrow(notedOp,
1683                                 resolvedAttributionSource, message, skipProxyOperation);
1684                     } catch (SecurityException e) {
1685                         //TODO 195339480: remove
1686                         String msg = "Security exception for op " + notedOp + " with source "
1687                                 + attributionSource.getUid() + ":"
1688                                 + attributionSource.getPackageName() + ", "
1689                                 + attributionSource.getNextUid() + ":"
1690                                 + attributionSource.getNextPackageName();
1691                         if (attributionSource.getNext() != null) {
1692                             AttributionSource next = attributionSource.getNext();
1693                             msg = msg + ", " + next.getNextPackageName() + ":" + next.getNextUid();
1694                         }
1695                         throw new SecurityException(msg + ":" + e.getMessage());
1696                     }
1697                 }
1698                 return Math.max(checkedOpResult, notedOpResult);
1699             }
1700         }
1701 
getAttributionChainId(boolean startDataDelivery, AttributionSource source)1702         private static int getAttributionChainId(boolean startDataDelivery,
1703                 AttributionSource source) {
1704             if (source == null || source.getNext() == null || !startDataDelivery) {
1705                 return AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE;
1706             }
1707             int attributionChainId = sAttributionChainIds.incrementAndGet();
1708 
1709             // handle overflow
1710             if (attributionChainId < 0) {
1711                 attributionChainId = 0;
1712                 sAttributionChainIds.set(0);
1713             }
1714             return attributionChainId;
1715         }
1716 
resolvePackageName(@onNull Context context, @NonNull AttributionSource attributionSource)1717         private static @Nullable String resolvePackageName(@NonNull Context context,
1718                 @NonNull AttributionSource attributionSource) {
1719             if (attributionSource.getPackageName() != null) {
1720                 return attributionSource.getPackageName();
1721             }
1722             final String[] packageNames = context.getPackageManager().getPackagesForUid(
1723                     attributionSource.getUid());
1724             if (packageNames != null) {
1725                 // This is best effort if the caller doesn't pass a package. The security
1726                 // sandbox is UID, therefore we pick an arbitrary package.
1727                 return packageNames[0];
1728             }
1729             // Last resort to handle special UIDs like root, etc.
1730             return AppOpsManager.resolvePackageName(attributionSource.getUid(),
1731                     attributionSource.getPackageName());
1732         }
1733 
resolveAttributionSource( @onNull Context context, @NonNull AttributionSource attributionSource)1734         private static @NonNull AttributionSource resolveAttributionSource(
1735                 @NonNull Context context, @NonNull AttributionSource attributionSource) {
1736             if (attributionSource.getPackageName() != null) {
1737                 return attributionSource;
1738             }
1739             return attributionSource.withPackageName(resolvePackageName(context,
1740                     attributionSource));
1741         }
1742     }
1743 
1744     private static final class RegisteredAttribution {
1745         private final DeathRecipient mDeathRecipient;
1746         private final IBinder mToken;
1747         private final AtomicBoolean mFinished;
1748 
RegisteredAttribution(Context context, int op, AttributionSource source, boolean fromDatasource)1749         RegisteredAttribution(Context context, int op, AttributionSource source,
1750                 boolean fromDatasource) {
1751             mFinished = new AtomicBoolean(false);
1752             mDeathRecipient = () -> {
1753                 if (unregister()) {
1754                     PermissionCheckerService
1755                             .finishDataDelivery(context, op, source.asState(), fromDatasource);
1756                 }
1757             };
1758             mToken = source.getToken();
1759             if (mToken != null) {
1760                 try {
1761                     mToken.linkToDeath(mDeathRecipient, 0);
1762                 } catch (RemoteException e) {
1763                     mDeathRecipient.binderDied();
1764                 }
1765             }
1766         }
1767 
unregister()1768         public boolean unregister() {
1769             if (mFinished.compareAndSet(false, true)) {
1770                 try {
1771                     if (mToken != null) {
1772                         mToken.unlinkToDeath(mDeathRecipient, 0);
1773                     }
1774                 } catch (NoSuchElementException e) {
1775                     // do nothing
1776                 }
1777                 return true;
1778             }
1779             return false;
1780         }
1781     }
1782 }
1783