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