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