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