1 /* 2 * Copyright (C) 2022 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; 18 19 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; 20 21 import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; 22 import static com.android.server.pm.AppsFilterUtils.canQueryViaComponents; 23 import static com.android.server.pm.AppsFilterUtils.requestsQueryAllPackages; 24 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.content.pm.Flags; 28 import android.content.pm.SigningDetails; 29 import android.os.Binder; 30 import android.os.Handler; 31 import android.os.Process; 32 import android.os.Trace; 33 import android.os.UserHandle; 34 import android.text.TextUtils; 35 import android.util.ArrayMap; 36 import android.util.ArraySet; 37 import android.util.Slog; 38 import android.util.SparseArray; 39 40 import com.android.internal.annotations.VisibleForTesting; 41 import com.android.internal.util.function.QuadFunction; 42 import com.android.server.om.OverlayReferenceMapper; 43 import com.android.server.pm.pkg.AndroidPackage; 44 import com.android.server.pm.pkg.PackageStateInternal; 45 import com.android.server.pm.pkg.SharedUserApi; 46 import com.android.server.pm.snapshot.PackageDataSnapshot; 47 import com.android.server.utils.SnapshotCache; 48 import com.android.server.utils.Watched; 49 import com.android.server.utils.WatchedArrayMap; 50 import com.android.server.utils.WatchedArraySet; 51 import com.android.server.utils.WatchedSparseBooleanMatrix; 52 import com.android.server.utils.WatchedSparseSetArray; 53 54 import java.io.PrintWriter; 55 import java.util.Arrays; 56 import java.util.Objects; 57 import java.util.concurrent.atomic.AtomicBoolean; 58 59 /** 60 * AppsFilter is the entity responsible for filtering visibility between apps based on declarations 61 * in their manifests. This class implements the unlocked, read-only methods of AppsFilter. 62 * See {@link AppsFilterImpl} for the write methods that updates the internal structures. 63 */ 64 public abstract class AppsFilterBase implements AppsFilterSnapshot { 65 protected static final String TAG = "AppsFilter"; 66 67 // Logs all filtering instead of enforcing 68 protected static final boolean DEBUG_ALLOW_ALL = false; 69 protected static final boolean DEBUG_LOGGING = false; 70 public static final boolean DEBUG_TRACING = false; 71 72 // Allow some time for cache rebuilds. 73 protected static final int CACHE_REBUILD_DELAY_MIN_MS = 10000; 74 // With each new rebuild the delay doubles until it reaches max delay. 75 protected static final int CACHE_REBUILD_DELAY_MAX_MS = 10000; 76 77 /** 78 * This contains a list of app UIDs that are implicitly queryable because another app explicitly 79 * interacted with it. For example, if application A starts a service in application B, 80 * application B is implicitly allowed to query for application A; regardless of any manifest 81 * entries. 82 */ 83 @NonNull 84 @Watched 85 protected WatchedSparseSetArray<Integer> mImplicitlyQueryable; 86 @NonNull 87 protected SnapshotCache<WatchedSparseSetArray<Integer>> mImplicitQueryableSnapshot; 88 89 /** 90 * This contains a list of app UIDs that are implicitly queryable because another app explicitly 91 * interacted with it, but could keep across package updates. For example, if application A 92 * grants persistable uri permission to application B; regardless of any manifest entries. 93 */ 94 @NonNull 95 @Watched 96 protected WatchedSparseSetArray<Integer> mRetainedImplicitlyQueryable; 97 @NonNull 98 protected SnapshotCache<WatchedSparseSetArray<Integer>> mRetainedImplicitlyQueryableSnapshot; 99 100 /** 101 * A mapping from the set of App IDs that query other App IDs via package name to the 102 * list of packages that they can see. 103 */ 104 @NonNull 105 @Watched 106 protected WatchedSparseSetArray<Integer> mQueriesViaPackage; 107 @NonNull 108 protected SnapshotCache<WatchedSparseSetArray<Integer>> mQueriesViaPackageSnapshot; 109 110 /** 111 * A mapping from the set of App IDs that query others via component match to the list 112 * of packages that the they resolve to. 113 */ 114 @NonNull 115 @Watched 116 protected WatchedSparseSetArray<Integer> mQueriesViaComponent; 117 @NonNull 118 protected SnapshotCache<WatchedSparseSetArray<Integer>> mQueriesViaComponentSnapshot; 119 120 /** 121 * A mapping from the set of App IDs that query other App IDs via library name to the 122 * list of packages that they can see. 123 */ 124 @NonNull 125 @Watched 126 protected WatchedSparseSetArray<Integer> mQueryableViaUsesLibrary; 127 @NonNull 128 protected SnapshotCache<WatchedSparseSetArray<Integer>> mQueryableViaUsesLibrarySnapshot; 129 130 /** 131 * A mapping from the set of App IDs that query other App IDs via custom permissions to the 132 * list of packages that they can see. 133 */ 134 @NonNull 135 @Watched 136 protected WatchedSparseSetArray<Integer> mQueryableViaUsesPermission; 137 @NonNull 138 protected SnapshotCache<WatchedSparseSetArray<Integer>> mQueryableViaUsesPermissionSnapshot; 139 140 /** 141 * Handler for running tasks such as building the initial visibility cache. 142 */ 143 protected Handler mHandler; 144 145 /** 146 * Pending full recompute of mQueriesViaComponent. Occurs when a package adds a new set of 147 * protected broadcast. This in turn invalidates all prior additions and require a very 148 * computationally expensive recomputing. 149 * Full recompute is done lazily at the point when we use mQueriesViaComponent to filter apps. 150 */ 151 protected AtomicBoolean mQueriesViaComponentRequireRecompute = new AtomicBoolean(false); 152 153 /** 154 * A set of App IDs that are always queryable by any package, regardless of their manifest 155 * content. 156 */ 157 @NonNull 158 @Watched 159 protected WatchedArraySet<Integer> mForceQueryable; 160 @NonNull 161 protected SnapshotCache<WatchedArraySet<Integer>> mForceQueryableSnapshot; 162 163 /** 164 * The set of package names provided by the device that should be force queryable regardless of 165 * their manifest contents. 166 */ 167 @NonNull 168 protected String[] mForceQueryableByDevicePackageNames; 169 @NonNull 170 /** True if all system apps should be made queryable by default. */ 171 protected boolean mSystemAppsQueryable; 172 @NonNull 173 protected FeatureConfig mFeatureConfig; 174 @NonNull 175 protected OverlayReferenceMapper mOverlayReferenceMapper; 176 @Nullable 177 protected SigningDetails mSystemSigningDetails; 178 179 @NonNull 180 @Watched 181 protected WatchedArraySet<String> mProtectedBroadcasts; 182 @NonNull 183 protected SnapshotCache<WatchedArraySet<String>> mProtectedBroadcastsSnapshot; 184 185 /** 186 * This structure maps uid -> uid and indicates whether access from the first should be 187 * filtered to the second. It's essentially a cache of the 188 * {@link #shouldFilterApplicationInternal(PackageDataSnapshot, int, Object, 189 * PackageStateInternal, int)} call. 190 * NOTE: It can only be relied upon after the system is ready to avoid unnecessary update on 191 * initial scam and is empty until {@link #mCacheReady} is true. 192 */ 193 @NonNull 194 @Watched 195 protected WatchedSparseBooleanMatrix mShouldFilterCache; 196 @NonNull 197 protected SnapshotCache<WatchedSparseBooleanMatrix> mShouldFilterCacheSnapshot; 198 199 protected volatile boolean mCacheReady = false; 200 protected volatile boolean mCacheEnabled = true; 201 protected volatile boolean mNeedToUpdateCacheForImplicitAccess = false; 202 203 protected static final boolean CACHE_VALID = true; 204 protected static final boolean CACHE_INVALID = false; 205 protected final AtomicBoolean mCacheValid = new AtomicBoolean(CACHE_INVALID); 206 isForceQueryable(int callingAppId)207 protected boolean isForceQueryable(int callingAppId) { 208 return mForceQueryable.contains(callingAppId); 209 } 210 isQueryableViaPackage(int callingAppId, int targetAppId)211 protected boolean isQueryableViaPackage(int callingAppId, int targetAppId) { 212 return mQueriesViaPackage.contains(callingAppId, targetAppId); 213 } 214 isQueryableViaComponent(int callingAppId, int targetAppId)215 protected boolean isQueryableViaComponent(int callingAppId, int targetAppId) { 216 return mQueriesViaComponent.contains(callingAppId, targetAppId); 217 } 218 isImplicitlyQueryable(int callingUid, int targetUid)219 protected boolean isImplicitlyQueryable(int callingUid, int targetUid) { 220 return mImplicitlyQueryable.contains(callingUid, targetUid); 221 } 222 isRetainedImplicitlyQueryable(int callingUid, int targetUid)223 protected boolean isRetainedImplicitlyQueryable(int callingUid, int targetUid) { 224 return mRetainedImplicitlyQueryable.contains(callingUid, targetUid); 225 } 226 isQueryableViaUsesLibrary(int callingAppId, int targetAppId)227 protected boolean isQueryableViaUsesLibrary(int callingAppId, int targetAppId) { 228 return mQueryableViaUsesLibrary.contains(callingAppId, targetAppId); 229 } 230 isQueryableViaUsesPermission(int callingAppId, int targetAppId)231 protected boolean isQueryableViaUsesPermission(int callingAppId, int targetAppId) { 232 return mQueryableViaUsesPermission.contains(callingAppId, targetAppId); 233 } 234 isQueryableViaComponentWhenRequireRecompute( ArrayMap<String, ? extends PackageStateInternal> existingSettings, PackageStateInternal callingPkgSetting, ArraySet<PackageStateInternal> callingSharedPkgSettings, AndroidPackage targetPkg, int callingAppId, int targetAppId)235 protected boolean isQueryableViaComponentWhenRequireRecompute( 236 ArrayMap<String, ? extends PackageStateInternal> existingSettings, 237 PackageStateInternal callingPkgSetting, 238 ArraySet<PackageStateInternal> callingSharedPkgSettings, 239 AndroidPackage targetPkg, 240 int callingAppId, int targetAppId) { 241 // Do no recompute or use mQueriesViaComponent if it's stale in snapshot 242 // Since we know we are in the snapshot, no need to acquire mLock because 243 // mProtectedBroadcasts will not change 244 if (callingPkgSetting != null) { 245 if (callingPkgSetting.getPkg() != null 246 && canQueryViaComponents(callingPkgSetting.getPkg(), targetPkg, 247 mProtectedBroadcasts)) { 248 return true; 249 } 250 } else { 251 for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) { 252 final AndroidPackage pkg = 253 callingSharedPkgSettings.valueAt(i).getPkg(); 254 if (pkg != null && canQueryViaComponents(pkg, targetPkg, 255 mProtectedBroadcasts)) { 256 return true; 257 } 258 } 259 } 260 return false; 261 } 262 263 /** 264 * See {@link AppsFilterSnapshot#getVisibilityAllowList(PackageDataSnapshot, 265 * PackageStateInternal, int[], ArrayMap)} 266 */ 267 @Override 268 @Nullable getVisibilityAllowList(PackageDataSnapshot snapshot, PackageStateInternal setting, int[] users, ArrayMap<String, ? extends PackageStateInternal> existingSettings)269 public SparseArray<int[]> getVisibilityAllowList(PackageDataSnapshot snapshot, 270 PackageStateInternal setting, int[] users, 271 ArrayMap<String, ? extends PackageStateInternal> existingSettings) { 272 if (isForceQueryable(setting.getAppId())) { 273 return null; 274 } 275 // let's reserve max memory to limit the number of allocations 276 SparseArray<int[]> result = new SparseArray<>(users.length); 277 for (int u = 0; u < users.length; u++) { 278 final int userId = users[u]; 279 int[] appIds = new int[existingSettings.size()]; 280 int[] buffer = null; 281 int allowListSize = 0; 282 for (int i = existingSettings.size() - 1; i >= 0; i--) { 283 final PackageStateInternal existingSetting = existingSettings.valueAt(i); 284 final int existingAppId = existingSetting.getAppId(); 285 if (existingAppId < Process.FIRST_APPLICATION_UID) { 286 continue; 287 } 288 final int loc = Arrays.binarySearch(appIds, 0, allowListSize, existingAppId); 289 if (loc >= 0) { 290 continue; 291 } 292 final int existingUid = UserHandle.getUid(userId, existingAppId); 293 if (!shouldFilterApplication(snapshot, existingUid, existingSetting, setting, 294 userId)) { 295 if (buffer == null) { 296 buffer = new int[appIds.length]; 297 } 298 final int insert = ~loc; 299 System.arraycopy(appIds, insert, buffer, 0, allowListSize - insert); 300 appIds[insert] = existingAppId; 301 System.arraycopy(buffer, 0, appIds, insert + 1, allowListSize - insert); 302 allowListSize++; 303 } 304 } 305 result.put(userId, Arrays.copyOf(appIds, allowListSize)); 306 } 307 return result; 308 } 309 310 /** 311 * This api does type conversion on the <existingSettings> parameter. 312 */ 313 @VisibleForTesting(visibility = PRIVATE) 314 @Nullable getVisibilityAllowList(PackageDataSnapshot snapshot, PackageStateInternal setting, int[] users, WatchedArrayMap<String, ? extends PackageStateInternal> existingSettings)315 SparseArray<int[]> getVisibilityAllowList(PackageDataSnapshot snapshot, 316 PackageStateInternal setting, int[] users, 317 WatchedArrayMap<String, ? extends PackageStateInternal> existingSettings) { 318 return getVisibilityAllowList(snapshot, setting, users, 319 existingSettings.untrackedStorage()); 320 } 321 isQueryableBySdkSandbox(int callingUid, int targetUid)322 private static boolean isQueryableBySdkSandbox(int callingUid, int targetUid) { 323 return Flags.allowSdkSandboxQueryIntentActivities() 324 && targetUid == Process.getAppUidForSdkSandboxUid(callingUid); 325 } 326 327 /** 328 * See 329 * {@link AppsFilterSnapshot#shouldFilterApplication(PackageDataSnapshot, int, Object, 330 * PackageStateInternal, int)} 331 */ 332 @Override shouldFilterApplication(PackageDataSnapshot snapshot, int callingUid, @Nullable Object callingSetting, PackageStateInternal targetPkgSetting, int userId)333 public boolean shouldFilterApplication(PackageDataSnapshot snapshot, int callingUid, 334 @Nullable Object callingSetting, PackageStateInternal targetPkgSetting, int userId) { 335 if (DEBUG_TRACING) { 336 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplication"); 337 } 338 try { 339 int callingAppId = UserHandle.getAppId(callingUid); 340 if (callingAppId < Process.FIRST_APPLICATION_UID 341 || targetPkgSetting.getAppId() < Process.FIRST_APPLICATION_UID 342 || callingAppId == targetPkgSetting.getAppId()) { 343 return false; 344 } else if (Process.isSdkSandboxUid(callingAppId)) { 345 final int targetAppId = targetPkgSetting.getAppId(); 346 final int targetUid = UserHandle.getUid(userId, targetAppId); 347 // we only allow sdk sandbox processes access to forcequeryable packages or 348 // if the target app is the sandbox's client app 349 return !isForceQueryable(targetPkgSetting.getAppId()) 350 && !isImplicitlyQueryable(callingUid, targetUid) 351 && !isQueryableBySdkSandbox(callingUid, targetUid); 352 } 353 // use cache 354 if (mCacheReady && mCacheEnabled) { 355 if (!shouldFilterApplicationUsingCache(callingUid, 356 targetPkgSetting.getAppId(), 357 userId)) { 358 return false; 359 } 360 } else { 361 if (!shouldFilterApplicationInternal((Computer) snapshot, 362 callingUid, callingSetting, targetPkgSetting, userId)) { 363 return false; 364 } 365 } 366 if (DEBUG_LOGGING || mFeatureConfig.isLoggingEnabled(callingAppId)) { 367 log(callingSetting, targetPkgSetting, "BLOCKED"); 368 } 369 return !DEBUG_ALLOW_ALL; 370 } finally { 371 if (DEBUG_TRACING) { 372 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 373 } 374 } 375 } 376 shouldFilterApplicationUsingCache(int callingUid, int appId, int userId)377 protected boolean shouldFilterApplicationUsingCache(int callingUid, int appId, int userId) { 378 final int callingIndex = mShouldFilterCache.indexOfKey(callingUid); 379 if (callingIndex < 0) { 380 Slog.wtf(TAG, "Encountered calling uid with no cached rules: " 381 + callingUid); 382 return true; 383 } 384 final int targetUid = UserHandle.getUid(userId, appId); 385 final int targetIndex = mShouldFilterCache.indexOfKey(targetUid); 386 if (targetIndex < 0) { 387 Slog.w(TAG, "Encountered calling -> target with no cached rules: " 388 + callingUid + " -> " + targetUid); 389 return true; 390 } 391 return mShouldFilterCache.valueAt(callingIndex, targetIndex); 392 } 393 shouldFilterApplicationInternal(Computer snapshot, int callingUid, Object callingSetting, PackageStateInternal targetPkgSetting, int targetUserId)394 protected boolean shouldFilterApplicationInternal(Computer snapshot, int callingUid, 395 Object callingSetting, PackageStateInternal targetPkgSetting, int targetUserId) { 396 if (DEBUG_TRACING) { 397 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplicationInternal"); 398 } 399 try { 400 final boolean featureEnabled = mFeatureConfig.isGloballyEnabled(); 401 if (!featureEnabled) { 402 if (DEBUG_LOGGING) { 403 Slog.d(TAG, "filtering disabled; skipped"); 404 } 405 return false; 406 } 407 if (callingSetting == null) { 408 Slog.wtf(TAG, "No setting found for non system uid " + callingUid); 409 return true; 410 } 411 412 if (DEBUG_TRACING) { 413 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "getAppId"); 414 } 415 final int callingAppId = UserHandle.getAppId(callingUid); 416 final int targetAppId = targetPkgSetting.getAppId(); 417 if (DEBUG_TRACING) { 418 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 419 } 420 if (callingAppId == targetAppId 421 || callingAppId < Process.FIRST_APPLICATION_UID 422 || targetAppId < Process.FIRST_APPLICATION_UID) { 423 if (DEBUG_LOGGING) { 424 log(callingSetting, targetPkgSetting, "same app id or core app id"); 425 } 426 return false; 427 } 428 429 final PackageStateInternal callingPkgSetting; 430 if (DEBUG_TRACING) { 431 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "callingSetting instanceof"); 432 } 433 final ArraySet<PackageStateInternal> callingSharedPkgSettings = new ArraySet<>(); 434 435 if (callingSetting instanceof PackageStateInternal) { 436 final PackageStateInternal packageState = (PackageStateInternal) callingSetting; 437 if (packageState.hasSharedUser()) { 438 callingPkgSetting = null; 439 final SharedUserApi sharedUserApi = 440 snapshot.getSharedUser(packageState.getSharedUserAppId()); 441 if (sharedUserApi != null) { 442 callingSharedPkgSettings.addAll(sharedUserApi.getPackageStates()); 443 } 444 } else { 445 callingPkgSetting = packageState; 446 } 447 } else { 448 callingPkgSetting = null; 449 callingSharedPkgSettings.addAll( 450 ((SharedUserSetting) callingSetting).getPackageStates()); 451 } 452 if (DEBUG_TRACING) { 453 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 454 } 455 456 if (callingPkgSetting != null) { 457 if (callingPkgSetting.getPkg() != null 458 && !mFeatureConfig.packageIsEnabled(callingPkgSetting.getPkg())) { 459 if (DEBUG_LOGGING) { 460 log(callingSetting, targetPkgSetting, "DISABLED"); 461 } 462 return false; 463 } 464 } else { 465 for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) { 466 final AndroidPackage pkg = callingSharedPkgSettings.valueAt(i).getPkg(); 467 if (pkg != null && !mFeatureConfig.packageIsEnabled(pkg)) { 468 if (DEBUG_LOGGING) { 469 log(callingSetting, targetPkgSetting, "DISABLED"); 470 } 471 return false; 472 } 473 } 474 } 475 476 try { 477 if (DEBUG_TRACING) { 478 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "requestsQueryAllPackages"); 479 } 480 if (callingPkgSetting != null) { 481 if (callingPkgSetting.getPkg() != null 482 && requestsQueryAllPackages(callingPkgSetting.getPkg())) { 483 return false; 484 } 485 } else { 486 for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) { 487 AndroidPackage pkg = callingSharedPkgSettings.valueAt(i).getPkg(); 488 if (pkg != null && requestsQueryAllPackages(pkg)) { 489 return false; 490 } 491 } 492 } 493 } finally { 494 if (DEBUG_TRACING) { 495 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 496 } 497 } 498 499 // This package isn't technically installed and won't be written to settings, so we can 500 // treat it as filtered until it's available again. 501 final AndroidPackage targetPkg = targetPkgSetting.getPkg(); 502 if (targetPkg == null) { 503 if (DEBUG_LOGGING) { 504 Slog.wtf(TAG, "shouldFilterApplication: " + "targetPkg is null"); 505 } 506 return true; 507 } 508 if (targetPkg.isStaticSharedLibrary()) { 509 // not an app, this filtering takes place at a higher level 510 return false; 511 } 512 513 try { 514 if (DEBUG_TRACING) { 515 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mForceQueryable"); 516 } 517 if (isForceQueryable(targetAppId)) { 518 if (DEBUG_LOGGING) { 519 log(callingSetting, targetPkgSetting, "force queryable"); 520 } 521 return false; 522 } 523 } finally { 524 if (DEBUG_TRACING) { 525 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 526 } 527 } 528 try { 529 if (DEBUG_TRACING) { 530 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueriesViaPackage"); 531 } 532 if (isQueryableViaPackage(callingAppId, targetAppId)) { 533 if (DEBUG_LOGGING) { 534 log(callingSetting, targetPkgSetting, "queries package"); 535 } 536 return false; 537 } 538 } finally { 539 if (DEBUG_TRACING) { 540 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 541 } 542 } 543 try { 544 if (DEBUG_TRACING) { 545 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueriesViaComponent"); 546 } 547 if (!mQueriesViaComponentRequireRecompute.get()) { 548 if (isQueryableViaComponent(callingAppId, targetAppId)) { 549 if (DEBUG_LOGGING) { 550 log(callingSetting, targetPkgSetting, "queries component"); 551 } 552 return false; 553 } 554 } else { // mQueriesViaComponent is stale 555 if (isQueryableViaComponentWhenRequireRecompute(snapshot.getPackageStates(), 556 callingPkgSetting, callingSharedPkgSettings, targetPkg, 557 callingAppId, targetAppId)) { 558 if (DEBUG_LOGGING) { 559 log(callingSetting, targetPkgSetting, "queries component"); 560 } 561 return false; 562 } 563 } 564 } finally { 565 if (DEBUG_TRACING) { 566 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 567 } 568 } 569 570 try { 571 if (DEBUG_TRACING) { 572 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mImplicitlyQueryable"); 573 } 574 final int targetUid = UserHandle.getUid(targetUserId, targetAppId); 575 if (isImplicitlyQueryable(callingUid, targetUid)) { 576 if (DEBUG_LOGGING) { 577 log(callingSetting, targetPkgSetting, "implicitly queryable for user"); 578 } 579 return false; 580 } 581 } finally { 582 if (DEBUG_TRACING) { 583 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 584 } 585 } 586 587 try { 588 if (DEBUG_TRACING) { 589 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mRetainedImplicitlyQueryable"); 590 } 591 final int targetUid = UserHandle.getUid(targetUserId, targetAppId); 592 if (isRetainedImplicitlyQueryable(callingUid, targetUid)) { 593 if (DEBUG_LOGGING) { 594 log(callingSetting, targetPkgSetting, 595 "retained implicitly queryable for user"); 596 } 597 return false; 598 } 599 } finally { 600 if (DEBUG_TRACING) { 601 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 602 } 603 } 604 605 try { 606 if (DEBUG_TRACING) { 607 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mOverlayReferenceMapper"); 608 } 609 final String targetName = targetPkg.getPackageName(); 610 if (!callingSharedPkgSettings.isEmpty()) { 611 int size = callingSharedPkgSettings.size(); 612 for (int index = 0; index < size; index++) { 613 PackageStateInternal pkgSetting = callingSharedPkgSettings.valueAt(index); 614 if (mOverlayReferenceMapper.isValidActor(targetName, 615 pkgSetting.getPackageName())) { 616 if (DEBUG_LOGGING) { 617 log(callingPkgSetting, targetPkgSetting, 618 "matches shared user of package that acts on target of " 619 + "overlay"); 620 } 621 return false; 622 } 623 } 624 } else { 625 if (mOverlayReferenceMapper.isValidActor(targetName, 626 callingPkgSetting.getPackageName())) { 627 if (DEBUG_LOGGING) { 628 log(callingPkgSetting, targetPkgSetting, "acts on target of overlay"); 629 } 630 return false; 631 } 632 } 633 } finally { 634 if (DEBUG_TRACING) { 635 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 636 } 637 } 638 639 try { 640 if (DEBUG_TRACING) { 641 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueryableViaUsesLibrary"); 642 } 643 if (isQueryableViaUsesLibrary(callingAppId, targetAppId)) { 644 if (DEBUG_LOGGING) { 645 log(callingSetting, targetPkgSetting, "queryable for library users"); 646 } 647 return false; 648 } 649 } finally { 650 if (DEBUG_TRACING) { 651 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 652 } 653 } 654 655 try { 656 if (DEBUG_TRACING) { 657 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueryableViaUsesPermission"); 658 } 659 if (isQueryableViaUsesPermission(callingAppId, targetAppId)) { 660 if (DEBUG_LOGGING) { 661 log(callingSetting, targetPkgSetting, "queryable for permission users"); 662 } 663 return false; 664 } 665 } finally { 666 if (DEBUG_TRACING) { 667 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 668 } 669 } 670 671 return true; 672 } finally { 673 if (DEBUG_TRACING) { 674 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 675 } 676 } 677 } 678 679 /** 680 * See {@link AppsFilterSnapshot#canQueryPackage(AndroidPackage, String)} 681 */ 682 @Override canQueryPackage(@onNull AndroidPackage querying, String potentialTarget)683 public boolean canQueryPackage(@NonNull AndroidPackage querying, String potentialTarget) { 684 int appId = UserHandle.getAppId(querying.getUid()); 685 if (appId < Process.FIRST_APPLICATION_UID) { 686 return true; 687 } 688 689 // Check if FILTER_APPLICATION_QUERY is enabled on the given package. 690 if (!mFeatureConfig.packageIsEnabled(querying)) { 691 return true; 692 } 693 694 if (requestsQueryAllPackages(querying)) { 695 return true; 696 } 697 698 return !querying.getQueriesPackages().isEmpty() 699 && querying.getQueriesPackages().contains(potentialTarget); 700 } 701 log(Object callingSetting, PackageStateInternal targetPkgSetting, String description)702 private static void log(Object callingSetting, PackageStateInternal targetPkgSetting, 703 String description) { 704 Slog.i(TAG, 705 "interaction: " + (callingSetting == null ? "system" : callingSetting) + " -> " 706 + targetPkgSetting + " " + description); 707 } 708 709 /** 710 * See {@link AppsFilterSnapshot#dumpQueries(PrintWriter, Integer, DumpState, int[], 711 * QuadFunction)} 712 */ 713 @Override dumpQueries( PrintWriter pw, @Nullable Integer filteringAppId, DumpState dumpState, int[] users, QuadFunction<Integer, Integer, Integer, Boolean, String[]> getPackagesForUid)714 public void dumpQueries( 715 PrintWriter pw, @Nullable Integer filteringAppId, DumpState dumpState, int[] users, 716 QuadFunction<Integer, Integer, Integer, Boolean, String[]> getPackagesForUid) { 717 final SparseArray<String> cache = new SparseArray<>(); 718 ToString<Integer> expandPackages = input -> { 719 String cachedValue = cache.get(input); 720 if (cachedValue == null) { 721 final int callingUid = Binder.getCallingUid(); 722 final int appId = UserHandle.getAppId(input); 723 String[] packagesForUid = null; 724 for (int i = 0, size = users.length; packagesForUid == null && i < size; i++) { 725 packagesForUid = getPackagesForUid.apply(callingUid, users[i], appId, 726 false /*isCallerInstantApp*/); 727 } 728 if (packagesForUid == null) { 729 cachedValue = "[app id " + input + " not installed]"; 730 } else { 731 cachedValue = packagesForUid.length == 1 ? packagesForUid[0] 732 : "[" + TextUtils.join(",", packagesForUid) + "]"; 733 } 734 cache.put(input, cachedValue); 735 } 736 return cachedValue; 737 }; 738 pw.println(); 739 pw.println("Queries:"); 740 dumpState.onTitlePrinted(); 741 if (!mFeatureConfig.isGloballyEnabled()) { 742 pw.println(" DISABLED"); 743 if (!DEBUG_LOGGING) { 744 return; 745 } 746 } 747 pw.println(" system apps queryable: " + mSystemAppsQueryable); 748 dumpForceQueryable(pw, filteringAppId, expandPackages); 749 dumpQueriesViaPackage(pw, filteringAppId, expandPackages); 750 dumpQueriesViaComponent(pw, filteringAppId, expandPackages); 751 dumpQueriesViaImplicitlyQueryable(pw, filteringAppId, users, expandPackages); 752 dumpQueriesViaUsesLibrary(pw, filteringAppId, expandPackages); 753 } 754 dumpForceQueryable(PrintWriter pw, @Nullable Integer filteringAppId, ToString<Integer> expandPackages)755 protected void dumpForceQueryable(PrintWriter pw, @Nullable Integer filteringAppId, 756 ToString<Integer> expandPackages) { 757 pw.println(" queries via forceQueryable:"); 758 dumpPackageSet(pw, filteringAppId, mForceQueryable.untrackedStorage(), 759 "forceQueryable", " ", expandPackages); 760 } 761 dumpQueriesViaPackage(PrintWriter pw, @Nullable Integer filteringAppId, ToString<Integer> expandPackages)762 protected void dumpQueriesViaPackage(PrintWriter pw, @Nullable Integer filteringAppId, 763 ToString<Integer> expandPackages) { 764 pw.println(" queries via package name:"); 765 dumpQueriesMap(pw, filteringAppId, mQueriesViaPackage, " ", expandPackages); 766 } 767 dumpQueriesViaComponent(PrintWriter pw, @Nullable Integer filteringAppId, ToString<Integer> expandPackages)768 protected void dumpQueriesViaComponent(PrintWriter pw, @Nullable Integer filteringAppId, 769 ToString<Integer> expandPackages) { 770 pw.println(" queries via component:"); 771 dumpQueriesMap(pw, filteringAppId, mQueriesViaComponent, " ", expandPackages); 772 } 773 dumpQueriesViaImplicitlyQueryable(PrintWriter pw, @Nullable Integer filteringAppId, int[] users, ToString<Integer> expandPackages)774 protected void dumpQueriesViaImplicitlyQueryable(PrintWriter pw, 775 @Nullable Integer filteringAppId, int[] users, ToString<Integer> expandPackages) { 776 pw.println(" queryable via interaction:"); 777 for (int user : users) { 778 pw.append(" User ").append(Integer.toString(user)).println(":"); 779 dumpQueriesMap(pw, 780 filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId), 781 mImplicitlyQueryable, " ", expandPackages); 782 dumpQueriesMap(pw, 783 filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId), 784 mRetainedImplicitlyQueryable, " ", expandPackages); 785 } 786 } 787 dumpQueriesViaUsesLibrary(PrintWriter pw, @Nullable Integer filteringAppId, ToString<Integer> expandPackages)788 protected void dumpQueriesViaUsesLibrary(PrintWriter pw, @Nullable Integer filteringAppId, 789 ToString<Integer> expandPackages) { 790 pw.println(" queryable via uses-library:"); 791 dumpQueriesMap(pw, filteringAppId, mQueryableViaUsesLibrary, " ", 792 expandPackages); 793 } 794 dumpQueriesViaUsesPermission(PrintWriter pw, @Nullable Integer filteringAppId, ToString<Integer> expandPackages)795 protected void dumpQueriesViaUsesPermission(PrintWriter pw, @Nullable Integer filteringAppId, 796 ToString<Integer> expandPackages) { 797 pw.println(" queryable via uses-permission:"); 798 dumpQueriesMap(pw, filteringAppId, mQueryableViaUsesPermission, " ", 799 expandPackages); 800 } 801 dumpQueriesMap(PrintWriter pw, @Nullable Integer filteringId, WatchedSparseSetArray<Integer> queriesMap, String spacing, @Nullable ToString<Integer> toString)802 private static void dumpQueriesMap(PrintWriter pw, @Nullable Integer filteringId, 803 WatchedSparseSetArray<Integer> queriesMap, String spacing, 804 @Nullable ToString<Integer> toString) { 805 for (int i = 0; i < queriesMap.size(); i++) { 806 Integer callingId = queriesMap.keyAt(i); 807 if (Objects.equals(callingId, filteringId)) { 808 // don't filter target package names if the calling is filteringId 809 dumpPackageSet( 810 pw, null /*filteringId*/, queriesMap.get(callingId), 811 toString == null 812 ? callingId.toString() 813 : toString.toString(callingId), 814 spacing, toString); 815 } else { 816 dumpPackageSet( 817 pw, filteringId, queriesMap.get(callingId), 818 toString == null 819 ? callingId.toString() 820 : toString.toString(callingId), 821 spacing, toString); 822 } 823 } 824 } 825 826 protected interface ToString<T> { toString(T input)827 String toString(T input); 828 } 829 dumpPackageSet(PrintWriter pw, @Nullable T filteringId, ArraySet<T> targetPkgSet, String subTitle, String spacing, @Nullable ToString<T> toString)830 private static <T> void dumpPackageSet(PrintWriter pw, @Nullable T filteringId, 831 ArraySet<T> targetPkgSet, String subTitle, String spacing, 832 @Nullable ToString<T> toString) { 833 if (targetPkgSet != null && targetPkgSet.size() > 0 834 && (filteringId == null || targetPkgSet.contains(filteringId))) { 835 pw.append(spacing).append(subTitle).println(":"); 836 for (T item : targetPkgSet) { 837 if (filteringId == null || Objects.equals(filteringId, item)) { 838 pw.append(spacing).append(" ") 839 .println(toString == null ? item : toString.toString(item)); 840 } 841 } 842 } 843 } 844 } 845