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