1 /* 2 * Copyright (C) 2019 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 import static android.os.UserHandle.USER_ALL; 21 import static android.os.UserHandle.USER_NULL; 22 import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE; 23 24 import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; 25 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_MANAGER_APPS_FILTER_CACHE_BUILD_REPORTED; 26 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_MANAGER_APPS_FILTER_CACHE_BUILD_REPORTED__EVENT_TYPE__BOOT; 27 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_MANAGER_APPS_FILTER_CACHE_BUILD_REPORTED__EVENT_TYPE__USER_CREATED; 28 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_MANAGER_APPS_FILTER_CACHE_BUILD_REPORTED__EVENT_TYPE__USER_DELETED; 29 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED; 30 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED__EVENT_TYPE__COMPAT_CHANGED; 31 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED__EVENT_TYPE__PACKAGE_ADDED; 32 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED__EVENT_TYPE__PACKAGE_DELETED; 33 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED__EVENT_TYPE__PACKAGE_REPLACED; 34 import static com.android.server.pm.AppsFilterUtils.canQueryAsInstaller; 35 import static com.android.server.pm.AppsFilterUtils.canQueryAsUpdateOwner; 36 import static com.android.server.pm.AppsFilterUtils.canQueryViaComponents; 37 import static com.android.server.pm.AppsFilterUtils.canQueryViaPackage; 38 import static com.android.server.pm.AppsFilterUtils.canQueryViaUsesLibrary; 39 40 import android.annotation.NonNull; 41 import android.annotation.Nullable; 42 import android.annotation.UserIdInt; 43 import android.app.ApplicationPackageManager; 44 import android.content.pm.PackageManager; 45 import android.content.pm.PackageManagerInternal; 46 import android.content.pm.SigningDetails; 47 import android.content.pm.UserInfo; 48 import android.os.Handler; 49 import android.os.SystemClock; 50 import android.os.SystemProperties; 51 import android.os.Trace; 52 import android.os.UserHandle; 53 import android.provider.DeviceConfig; 54 import android.util.ArrayMap; 55 import android.util.ArraySet; 56 import android.util.Slog; 57 import android.util.SparseBooleanArray; 58 import android.util.SparseSetArray; 59 60 import com.android.internal.R; 61 import com.android.internal.annotations.GuardedBy; 62 import com.android.internal.annotations.VisibleForTesting; 63 import com.android.internal.pm.pkg.component.ParsedInstrumentation; 64 import com.android.internal.pm.pkg.component.ParsedPermission; 65 import com.android.internal.pm.pkg.component.ParsedUsesPermission; 66 import com.android.internal.util.ArrayUtils; 67 import com.android.internal.util.FrameworkStatsLog; 68 import com.android.server.FgThread; 69 import com.android.server.compat.CompatChange; 70 import com.android.server.om.OverlayReferenceMapper; 71 import com.android.server.pm.AppsFilterUtils.ParallelComputeComponentVisibility; 72 import com.android.server.pm.parsing.pkg.AndroidPackageUtils; 73 import com.android.server.pm.pkg.AndroidPackage; 74 import com.android.server.pm.pkg.PackageStateInternal; 75 import com.android.server.pm.pkg.SharedUserApi; 76 import com.android.server.utils.Snappable; 77 import com.android.server.utils.SnapshotCache; 78 import com.android.server.utils.Watchable; 79 import com.android.server.utils.WatchableImpl; 80 import com.android.server.utils.WatchedArraySet; 81 import com.android.server.utils.WatchedSparseBooleanMatrix; 82 import com.android.server.utils.WatchedSparseSetArray; 83 import com.android.server.utils.Watcher; 84 85 import java.util.ArrayList; 86 import java.util.Arrays; 87 import java.util.List; 88 import java.util.Objects; 89 90 /** 91 * Implementation of the methods that update the internal structures of AppsFilter. Because of the 92 * mutations, all the read accesses to those internal structures need to be locked, thus extending 93 * {@link AppsFilterLocked}. 94 */ 95 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) 96 public final class AppsFilterImpl extends AppsFilterLocked implements Watchable, Snappable { 97 /** 98 * A cached snapshot. 99 */ 100 @NonNull 101 private final SnapshotCache<AppsFilterSnapshot> mSnapshot; 102 103 /** 104 * Watchable machinery 105 */ 106 private final WatchableImpl mWatchable = new WatchableImpl(); 107 108 /** 109 * A cache that maps parsed {@link android.R.styleable#AndroidManifestPermission 110 * <permission>} to the packages that define them. While computing visibility based on 111 * permissions, this cache is used to save the cost of reading through every existing package 112 * to determine the App Ids that define a particular permission. 113 */ 114 @GuardedBy("mQueryableViaUsesPermissionLock") 115 @NonNull 116 private final ArrayMap<String, ArraySet<Integer>> mPermissionToUids; 117 118 /** 119 * A cache that maps parsed {@link android.R.styleable#AndroidManifestUsesPermission 120 * <uses-permission>} to the packages that request them. While computing visibility based 121 * on permissions, this cache is used to save the cost of reading through every existing 122 * package to determine the App Ids that request a particular permission. 123 */ 124 @GuardedBy("mQueryableViaUsesPermissionLock") 125 @NonNull 126 private final ArrayMap<String, ArraySet<Integer>> mUsesPermissionToUids; 127 128 /** 129 * Ensures an observer is in the list, exactly once. The observer cannot be null. The 130 * function quietly returns if the observer is already in the list. 131 * 132 * @param observer The {@link Watcher} to be notified when the {@link Watchable} changes. 133 */ 134 @Override registerObserver(@onNull Watcher observer)135 public void registerObserver(@NonNull Watcher observer) { 136 mWatchable.registerObserver(observer); 137 } 138 139 /** 140 * Ensures an observer is not in the list. The observer must not be null. The function 141 * quietly returns if the objserver is not in the list. 142 * 143 * @param observer The {@link Watcher} that should not be in the notification list. 144 */ 145 @Override unregisterObserver(@onNull Watcher observer)146 public void unregisterObserver(@NonNull Watcher observer) { 147 mWatchable.unregisterObserver(observer); 148 } 149 150 /** 151 * Return true if the {@link Watcher) is a registered observer. 152 * 153 * @param observer A {@link Watcher} that might be registered 154 * @return true if the observer is registered with this {@link Watchable}. 155 */ 156 @Override isRegisteredObserver(@onNull Watcher observer)157 public boolean isRegisteredObserver(@NonNull Watcher observer) { 158 return mWatchable.isRegisteredObserver(observer); 159 } 160 161 /** 162 * Invokes {@link Watcher#onChange} on each registered observer. The method can be called 163 * with the {@link Watchable} that generated the event. In a tree of {@link Watchable}s, this 164 * is generally the first (deepest) {@link Watchable} to detect a change. 165 * 166 * @param what The {@link Watchable} that generated the event. 167 */ 168 @Override dispatchChange(@ullable Watchable what)169 public void dispatchChange(@Nullable Watchable what) { 170 mWatchable.dispatchChange(what); 171 } 172 173 /** 174 * Report a change to observers. 175 */ onChanged()176 private void onChanged() { 177 // App visibility may have changed, which means that earlier fetches from these caches may 178 // be invalid. 179 PackageManager.invalidatePackageInfoCache(); 180 ApplicationPackageManager.invalidateGetPackagesForUidCache(); 181 dispatchChange(this); 182 } 183 invalidateCache(String reason)184 private void invalidateCache(String reason) { 185 if (mCacheValid.compareAndSet(CACHE_VALID, CACHE_INVALID)) { 186 Slog.i(TAG, "Invalidating cache: " + reason); 187 } 188 } 189 190 @VisibleForTesting(visibility = PRIVATE) AppsFilterImpl(FeatureConfig featureConfig, String[] forceQueryableList, boolean systemAppsQueryable, @Nullable OverlayReferenceMapper.Provider overlayProvider, Handler handler)191 AppsFilterImpl(FeatureConfig featureConfig, 192 String[] forceQueryableList, 193 boolean systemAppsQueryable, 194 @Nullable OverlayReferenceMapper.Provider overlayProvider, 195 Handler handler) { 196 mFeatureConfig = featureConfig; 197 mForceQueryableByDevicePackageNames = forceQueryableList; 198 mSystemAppsQueryable = systemAppsQueryable; 199 mOverlayReferenceMapper = new OverlayReferenceMapper(true /*deferRebuild*/, 200 overlayProvider); 201 mHandler = handler; 202 mShouldFilterCache = new WatchedSparseBooleanMatrix(); 203 mShouldFilterCacheSnapshot = new SnapshotCache.Auto<>( 204 mShouldFilterCache, mShouldFilterCache, "AppsFilter.mShouldFilterCache"); 205 mImplicitlyQueryable = new WatchedSparseSetArray<>(); 206 mImplicitQueryableSnapshot = new SnapshotCache.Auto<>( 207 mImplicitlyQueryable, mImplicitlyQueryable, "AppsFilter.mImplicitlyQueryable"); 208 mRetainedImplicitlyQueryable = new WatchedSparseSetArray<>(); 209 mRetainedImplicitlyQueryableSnapshot = new SnapshotCache.Auto<>( 210 mRetainedImplicitlyQueryable, mRetainedImplicitlyQueryable, 211 "AppsFilter.mRetainedImplicitlyQueryable"); 212 mQueriesViaPackage = new WatchedSparseSetArray<>(); 213 mQueriesViaPackageSnapshot = new SnapshotCache.Auto<>( 214 mQueriesViaPackage, mQueriesViaPackage, "AppsFilter.mQueriesViaPackage"); 215 mQueriesViaComponent = new WatchedSparseSetArray<>(); 216 mQueriesViaComponentSnapshot = new SnapshotCache.Auto<>( 217 mQueriesViaComponent, mQueriesViaComponent, "AppsFilter.mQueriesViaComponent"); 218 mQueryableViaUsesLibrary = new WatchedSparseSetArray<>(); 219 mQueryableViaUsesLibrarySnapshot = new SnapshotCache.Auto<>( 220 mQueryableViaUsesLibrary, mQueryableViaUsesLibrary, 221 "AppsFilter.mQueryableViaUsesLibrary"); 222 mQueryableViaUsesPermission = new WatchedSparseSetArray<>(); 223 mQueryableViaUsesPermissionSnapshot = new SnapshotCache.Auto<>( 224 mQueryableViaUsesPermission, mQueryableViaUsesPermission, 225 "AppsFilter.mQueryableViaUsesPermission"); 226 mForceQueryable = new WatchedArraySet<>(); 227 mForceQueryableSnapshot = new SnapshotCache.Auto<>( 228 mForceQueryable, mForceQueryable, "AppsFilter.mForceQueryable"); 229 mProtectedBroadcasts = new WatchedArraySet<>(); 230 mProtectedBroadcastsSnapshot = new SnapshotCache.Auto<>( 231 mProtectedBroadcasts, mProtectedBroadcasts, "AppsFilter.mProtectedBroadcasts"); 232 mPermissionToUids = new ArrayMap<>(); 233 mUsesPermissionToUids = new ArrayMap<>(); 234 235 mSnapshot = new SnapshotCache<AppsFilterSnapshot>(this, this) { 236 @Override 237 public AppsFilterSnapshot createSnapshot() { 238 return new AppsFilterSnapshotImpl(AppsFilterImpl.this); 239 } 240 }; 241 readCacheEnabledSysProp(); 242 SystemProperties.addChangeCallback(this::readCacheEnabledSysProp); 243 } 244 readCacheEnabledSysProp()245 private void readCacheEnabledSysProp() { 246 mCacheEnabled = SystemProperties.getBoolean("debug.pm.use_app_filter_cache", true); 247 } 248 249 /** 250 * Return a snapshot. If the cached snapshot is null, build a new one. The logic in 251 * the function ensures that this function returns a valid snapshot even if a race 252 * condition causes the cached snapshot to be cleared asynchronously to this method. 253 */ snapshot()254 public AppsFilterSnapshot snapshot() { 255 return mSnapshot.snapshot(); 256 } 257 258 private static class FeatureConfigImpl implements FeatureConfig, 259 CompatChange.ChangeListener { 260 private static final String FILTERING_ENABLED_NAME = "package_query_filtering_enabled"; 261 private final PackageManagerServiceInjector mInjector; 262 private final PackageManagerInternal mPmInternal; 263 private volatile boolean mFeatureEnabled = 264 PackageManager.APP_ENUMERATION_ENABLED_BY_DEFAULT; 265 @GuardedBy("mDisabledPackages") 266 private final ArraySet<String> mDisabledPackages = new ArraySet<>(); 267 268 @Nullable 269 private SparseBooleanArray mLoggingEnabled = null; 270 private AppsFilterImpl mAppsFilter; 271 FeatureConfigImpl( PackageManagerInternal pmInternal, PackageManagerServiceInjector injector)272 private FeatureConfigImpl( 273 PackageManagerInternal pmInternal, PackageManagerServiceInjector injector) { 274 mPmInternal = pmInternal; 275 mInjector = injector; 276 } 277 FeatureConfigImpl(FeatureConfigImpl orig)278 FeatureConfigImpl(FeatureConfigImpl orig) { 279 mInjector = null; 280 mPmInternal = null; 281 mFeatureEnabled = orig.mFeatureEnabled; 282 synchronized (orig.mDisabledPackages) { 283 mDisabledPackages.addAll(orig.mDisabledPackages); 284 } 285 mLoggingEnabled = orig.mLoggingEnabled; 286 } 287 setAppsFilter(AppsFilterImpl filter)288 public void setAppsFilter(AppsFilterImpl filter) { 289 mAppsFilter = filter; 290 } 291 292 @Override onSystemReady()293 public void onSystemReady() { 294 mFeatureEnabled = DeviceConfig.getBoolean( 295 NAMESPACE_PACKAGE_MANAGER_SERVICE, FILTERING_ENABLED_NAME, 296 PackageManager.APP_ENUMERATION_ENABLED_BY_DEFAULT); 297 DeviceConfig.addOnPropertiesChangedListener( 298 NAMESPACE_PACKAGE_MANAGER_SERVICE, FgThread.getExecutor(), 299 properties -> { 300 if (properties.getKeyset().contains(FILTERING_ENABLED_NAME)) { 301 synchronized (FeatureConfigImpl.this) { 302 mFeatureEnabled = properties.getBoolean(FILTERING_ENABLED_NAME, 303 PackageManager.APP_ENUMERATION_ENABLED_BY_DEFAULT); 304 } 305 } 306 }); 307 mInjector.getCompatibility().registerListener( 308 PackageManager.FILTER_APPLICATION_QUERY, this); 309 } 310 311 @Override isGloballyEnabled()312 public boolean isGloballyEnabled() { 313 if (DEBUG_TRACING) { 314 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "isGloballyEnabled"); 315 } 316 try { 317 return mFeatureEnabled; 318 } finally { 319 if (DEBUG_TRACING) { 320 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 321 } 322 } 323 } 324 325 @Override packageIsEnabled(AndroidPackage pkg)326 public boolean packageIsEnabled(AndroidPackage pkg) { 327 if (DEBUG_TRACING) { 328 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "packageIsEnabled"); 329 } 330 try { 331 synchronized (mDisabledPackages) { 332 return !mDisabledPackages.contains(pkg.getPackageName()); 333 } 334 } finally { 335 if (DEBUG_TRACING) { 336 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 337 } 338 } 339 } 340 341 @Override isLoggingEnabled(int uid)342 public boolean isLoggingEnabled(int uid) { 343 return mLoggingEnabled != null && mLoggingEnabled.indexOfKey(uid) >= 0; 344 } 345 346 @Override enableLogging(int appId, boolean enable)347 public void enableLogging(int appId, boolean enable) { 348 if (enable) { 349 if (mLoggingEnabled == null) { 350 mLoggingEnabled = new SparseBooleanArray(); 351 } 352 mLoggingEnabled.put(appId, true); 353 } else { 354 if (mLoggingEnabled != null) { 355 final int index = mLoggingEnabled.indexOfKey(appId); 356 if (index >= 0) { 357 mLoggingEnabled.removeAt(index); 358 if (mLoggingEnabled.size() == 0) { 359 mLoggingEnabled = null; 360 } 361 } 362 } 363 } 364 } 365 366 @Override onCompatChange(String packageName)367 public void onCompatChange(String packageName) { 368 Computer snapshot = (Computer) mPmInternal.snapshot(); 369 AndroidPackage pkg = snapshot.getPackage(packageName); 370 if (pkg == null) { 371 return; 372 } 373 final long currentTimeUs = SystemClock.currentTimeMicro(); 374 updateEnabledState(pkg); 375 mAppsFilter.updateShouldFilterCacheForPackage(snapshot, packageName); 376 mAppsFilter.logCacheUpdated( 377 PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED__EVENT_TYPE__COMPAT_CHANGED, 378 SystemClock.currentTimeMicro() - currentTimeUs, 379 snapshot.getUserInfos().length, 380 snapshot.getPackageStates().size(), 381 pkg.getUid()); 382 } 383 updateEnabledState(@onNull AndroidPackage pkg)384 private void updateEnabledState(@NonNull AndroidPackage pkg) { 385 // TODO(b/135203078): Do not use toAppInfo 386 // TODO(b/167551701): Make changeId non-logging 387 final boolean enabled = mInjector.getCompatibility().isChangeEnabledInternalNoLogging( 388 PackageManager.FILTER_APPLICATION_QUERY, 389 AndroidPackageUtils.generateAppInfoWithoutState(pkg)); 390 synchronized (mDisabledPackages) { 391 if (enabled) { 392 mDisabledPackages.remove(pkg.getPackageName()); 393 } else { 394 mDisabledPackages.add(pkg.getPackageName()); 395 } 396 } 397 if (mAppsFilter != null) { 398 mAppsFilter.onChanged(); 399 } 400 } 401 402 @Override updatePackageState(PackageStateInternal setting, boolean removed)403 public void updatePackageState(PackageStateInternal setting, boolean removed) { 404 final boolean enableLogging = setting.getPkg() != null 405 && !removed && (setting.getPkg().isTestOnly() 406 || setting.getPkg().isDebuggable()); 407 enableLogging(setting.getAppId(), enableLogging); 408 if (removed) { 409 synchronized (mDisabledPackages) { 410 mDisabledPackages.remove(setting.getPackageName()); 411 } 412 if (mAppsFilter != null) { 413 mAppsFilter.onChanged(); 414 } 415 } else if (setting.getPkg() != null) { 416 updateEnabledState(setting.getPkg()); 417 } 418 } 419 420 @Override snapshot()421 public FeatureConfig snapshot() { 422 return new FeatureConfigImpl(this); 423 } 424 } 425 426 /** Builder method for an AppsFilter */ create(@onNull PackageManagerServiceInjector injector, @NonNull PackageManagerInternal pmInt)427 public static AppsFilterImpl create(@NonNull PackageManagerServiceInjector injector, 428 @NonNull PackageManagerInternal pmInt) { 429 final boolean forceSystemAppsQueryable = 430 injector.getContext().getResources() 431 .getBoolean(R.bool.config_forceSystemPackagesQueryable); 432 final FeatureConfigImpl featureConfig = new FeatureConfigImpl(pmInt, injector); 433 final String[] forcedQueryablePackageNames; 434 if (forceSystemAppsQueryable) { 435 // all system apps already queryable, no need to read and parse individual exceptions 436 forcedQueryablePackageNames = new String[]{}; 437 } else { 438 forcedQueryablePackageNames = 439 injector.getContext().getResources() 440 .getStringArray(R.array.config_forceQueryablePackages); 441 for (int i = 0; i < forcedQueryablePackageNames.length; i++) { 442 forcedQueryablePackageNames[i] = forcedQueryablePackageNames[i].intern(); 443 } 444 } 445 AppsFilterImpl appsFilter = new AppsFilterImpl(featureConfig, 446 forcedQueryablePackageNames, forceSystemAppsQueryable, null, 447 injector.getHandler()); 448 featureConfig.setAppsFilter(appsFilter); 449 return appsFilter; 450 } 451 getFeatureConfig()452 public FeatureConfig getFeatureConfig() { 453 return mFeatureConfig; 454 } 455 456 /** 457 * Grants access based on an interaction between a calling and target package, granting 458 * visibility of the caller from the target. 459 * 460 * @param recipientUid the uid gaining visibility of the {@code visibleUid}. 461 * @param visibleUid the uid becoming visible to the {@recipientUid} 462 * @param retainOnUpdate if the implicit access retained across package updates. 463 * @return {@code true} if implicit access was not already granted. 464 */ grantImplicitAccess(int recipientUid, int visibleUid, boolean retainOnUpdate)465 public boolean grantImplicitAccess(int recipientUid, int visibleUid, boolean retainOnUpdate) { 466 if (recipientUid == visibleUid) { 467 return false; 468 } 469 final boolean changed; 470 synchronized (mImplicitlyQueryableLock) { 471 changed = retainOnUpdate 472 ? mRetainedImplicitlyQueryable.add(recipientUid, visibleUid) 473 : mImplicitlyQueryable.add(recipientUid, visibleUid); 474 if (!mCacheReady && changed) { 475 mNeedToUpdateCacheForImplicitAccess = true; 476 } 477 } 478 if (changed && DEBUG_LOGGING) { 479 Slog.i(TAG, (retainOnUpdate ? "retained " : "") + "implicit access granted: " 480 + recipientUid + " -> " + visibleUid); 481 } 482 483 if (mCacheReady) { 484 synchronized (mCacheLock) { 485 // Update the cache in a one-off manner since we've got all the information we need. 486 mShouldFilterCache.put(recipientUid, visibleUid, false); 487 } 488 } 489 if (changed) { 490 onChanged(); 491 } 492 return changed; 493 } 494 onSystemReady(PackageManagerInternal pmInternal)495 public void onSystemReady(PackageManagerInternal pmInternal) { 496 mOverlayReferenceMapper.rebuildIfDeferred(); 497 mFeatureConfig.onSystemReady(); 498 499 updateEntireShouldFilterCacheAsync(pmInternal, 500 PACKAGE_MANAGER_APPS_FILTER_CACHE_BUILD_REPORTED__EVENT_TYPE__BOOT); 501 } 502 503 /** 504 * Adds a package that should be considered when filtering visibility between apps. 505 * 506 * @param newPkgSetting the new setting being added 507 * @param isReplace if the package is being replaced and may need extra cleanup. 508 * @param retainImplicitGrantOnReplace {@code true} to retain implicit grant access if 509 * the package is being replaced. 510 */ addPackage(Computer snapshot, PackageStateInternal newPkgSetting, boolean isReplace, boolean retainImplicitGrantOnReplace)511 public void addPackage(Computer snapshot, PackageStateInternal newPkgSetting, 512 boolean isReplace, boolean retainImplicitGrantOnReplace) { 513 final long currentTimeUs = SystemClock.currentTimeMicro(); 514 final int logType = isReplace 515 ? PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED__EVENT_TYPE__PACKAGE_REPLACED 516 : PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED__EVENT_TYPE__PACKAGE_ADDED; 517 if (DEBUG_TRACING) { 518 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage"); 519 } 520 try { 521 if (isReplace) { 522 // let's first remove any prior rules for this package 523 removePackageInternal(snapshot, newPkgSetting, 524 true /*isReplace*/, retainImplicitGrantOnReplace); 525 } 526 final ArrayMap<String, ? extends PackageStateInternal> settings = 527 snapshot.getPackageStates(); 528 final UserInfo[] users = snapshot.getUserInfos(); 529 final ArraySet<String> additionalChangedPackages = 530 addPackageInternal(newPkgSetting, settings); 531 if (mCacheReady) { 532 synchronized (mCacheLock) { 533 updateShouldFilterCacheForPackage(snapshot, null, newPkgSetting, 534 settings, users, USER_ALL, settings.size()); 535 if (additionalChangedPackages != null) { 536 for (int index = 0; index < additionalChangedPackages.size(); index++) { 537 String changedPackage = additionalChangedPackages.valueAt(index); 538 PackageStateInternal changedPkgSetting = settings.get(changedPackage); 539 if (changedPkgSetting == null) { 540 // It's possible for the overlay mapper to know that an actor 541 // package changed via an explicit reference, even if the actor 542 // isn't installed, so skip if that's the case. 543 continue; 544 } 545 updateShouldFilterCacheForPackage(snapshot, null, changedPkgSetting, 546 settings, users, USER_ALL, settings.size()); 547 } 548 } 549 } 550 logCacheUpdated(logType, SystemClock.currentTimeMicro() - currentTimeUs, 551 users.length, settings.size(), newPkgSetting.getAppId()); 552 } else { 553 invalidateCache("addPackage: " + newPkgSetting.getPackageName()); 554 } 555 } finally { 556 onChanged(); 557 if (DEBUG_TRACING) { 558 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 559 } 560 } 561 } 562 563 /** 564 * @return Additional packages that may have had their viewing visibility changed and may need 565 * to be updated in the cache. Returns null if there are no additional packages. 566 */ 567 @Nullable addPackageInternal(PackageStateInternal newPkgSetting, ArrayMap<String, ? extends PackageStateInternal> existingSettings)568 private ArraySet<String> addPackageInternal(PackageStateInternal newPkgSetting, 569 ArrayMap<String, ? extends PackageStateInternal> existingSettings) { 570 if (Objects.equals("android", newPkgSetting.getPackageName())) { 571 // let's set aside the framework signatures 572 mSystemSigningDetails = newPkgSetting.getSigningDetails(); 573 // and since we add overlays before we add the framework, let's revisit already added 574 // packages for signature matches 575 for (PackageStateInternal setting : existingSettings.values()) { 576 if (isSystemSigned(mSystemSigningDetails, setting)) { 577 synchronized (mForceQueryableLock) { 578 mForceQueryable.add(setting.getAppId()); 579 } 580 } 581 } 582 } 583 584 final AndroidPackage newPkg = newPkgSetting.getPkg(); 585 if (newPkg == null) { 586 return null; 587 } 588 589 final List<String> newBroadcasts = newPkg.getProtectedBroadcasts(); 590 if (newBroadcasts.size() != 0) { 591 final boolean protectedBroadcastsChanged; 592 synchronized (mProtectedBroadcastsLock) { 593 final int oldSize = mProtectedBroadcasts.size(); 594 mProtectedBroadcasts.addAll(newBroadcasts); 595 protectedBroadcastsChanged = mProtectedBroadcasts.size() != oldSize; 596 } 597 if (protectedBroadcastsChanged) { 598 mQueriesViaComponentRequireRecompute.set(true); 599 } 600 } 601 602 final boolean newIsForceQueryable; 603 synchronized (mForceQueryableLock) { 604 newIsForceQueryable = mForceQueryable.contains(newPkgSetting.getAppId()) 605 /* shared user that is already force queryable */ 606 || newPkgSetting.isForceQueryableOverride() /* adb override */ 607 || (newPkgSetting.isSystem() && (mSystemAppsQueryable 608 || newPkg.isForceQueryable() 609 || ArrayUtils.contains(mForceQueryableByDevicePackageNames, 610 newPkg.getPackageName()))); 611 if (newIsForceQueryable 612 || (mSystemSigningDetails != null 613 && isSystemSigned(mSystemSigningDetails, newPkgSetting))) { 614 mForceQueryable.add(newPkgSetting.getAppId()); 615 } 616 } 617 618 if (!newPkg.getUsesPermissions().isEmpty()) { 619 // newPkg requests some permissions 620 synchronized (mQueryableViaUsesPermissionLock) { 621 for (ParsedUsesPermission usesPermission : newPkg.getUsesPermissions()) { 622 String usesPermissionName = usesPermission.getName(); 623 // Lookup in the mPermissionToUids cache if installed packages have 624 // defined this permission. 625 if (mPermissionToUids.containsKey(usesPermissionName)) { 626 final ArraySet<Integer> permissionDefiners = 627 mPermissionToUids.get(usesPermissionName); 628 for (int j = 0; j < permissionDefiners.size(); j++) { 629 final int targetAppId = permissionDefiners.valueAt(j); 630 if (targetAppId != newPkgSetting.getAppId()) { 631 mQueryableViaUsesPermission.add(newPkgSetting.getAppId(), 632 targetAppId); 633 } 634 } 635 } 636 // Record in mUsesPermissionToUids that a permission was requested 637 // by a new package 638 if (!mUsesPermissionToUids.containsKey(usesPermissionName)) { 639 mUsesPermissionToUids.put(usesPermissionName, new ArraySet<>()); 640 } 641 mUsesPermissionToUids.get(usesPermissionName).add(newPkgSetting.getAppId()); 642 } 643 } 644 } 645 if (!newPkg.getPermissions().isEmpty()) { 646 synchronized (mQueryableViaUsesPermissionLock) { 647 // newPkg defines some permissions 648 for (ParsedPermission permission : newPkg.getPermissions()) { 649 String permissionName = permission.getName(); 650 // Lookup in the mUsesPermissionToUids cache if installed packages have 651 // requested this permission. 652 if (mUsesPermissionToUids.containsKey(permissionName)) { 653 final ArraySet<Integer> permissionUsers = mUsesPermissionToUids.get( 654 permissionName); 655 for (int j = 0; j < permissionUsers.size(); j++) { 656 final int queryingAppId = permissionUsers.valueAt(j); 657 if (queryingAppId != newPkgSetting.getAppId()) { 658 mQueryableViaUsesPermission.add(queryingAppId, 659 newPkgSetting.getAppId()); 660 } 661 } 662 } 663 // Record in mPermissionToUids that a permission was defined by a new package 664 if (!mPermissionToUids.containsKey(permissionName)) { 665 mPermissionToUids.put(permissionName, new ArraySet<>()); 666 } 667 mPermissionToUids.get(permissionName).add(newPkgSetting.getAppId()); 668 } 669 } 670 } 671 672 for (int i = existingSettings.size() - 1; i >= 0; i--) { 673 final PackageStateInternal existingSetting = existingSettings.valueAt(i); 674 if (existingSetting.getAppId() == newPkgSetting.getAppId() 675 || existingSetting.getPkg() 676 == null) { 677 continue; 678 } 679 final AndroidPackage existingPkg = existingSetting.getPkg(); 680 // let's evaluate the ability of already added packages to see this new package 681 if (!newIsForceQueryable) { 682 if (!mQueriesViaComponentRequireRecompute.get() 683 && canQueryViaComponents(existingPkg, newPkg, mProtectedBroadcasts)) { 684 synchronized (mQueriesViaComponentLock) { 685 mQueriesViaComponent.add(existingSetting.getAppId(), 686 newPkgSetting.getAppId()); 687 } 688 } 689 if (canQueryViaPackage(existingPkg, newPkg) 690 || canQueryAsInstaller(existingSetting, newPkg) 691 || canQueryAsUpdateOwner(existingSetting, newPkg)) { 692 synchronized (mQueriesViaPackageLock) { 693 mQueriesViaPackage.add(existingSetting.getAppId(), 694 newPkgSetting.getAppId()); 695 } 696 } 697 if (canQueryViaUsesLibrary(existingPkg, newPkg)) { 698 synchronized (mQueryableViaUsesLibraryLock) { 699 mQueryableViaUsesLibrary.add(existingSetting.getAppId(), 700 newPkgSetting.getAppId()); 701 } 702 } 703 } 704 final boolean existingIsForceQueryable; 705 synchronized (mForceQueryableLock) { 706 existingIsForceQueryable = mForceQueryable.contains(existingSetting.getAppId()); 707 } 708 // now we'll evaluate our new package's ability to see existing packages 709 if (!existingIsForceQueryable) { 710 if (!mQueriesViaComponentRequireRecompute.get() 711 && canQueryViaComponents(newPkg, existingPkg, mProtectedBroadcasts)) { 712 synchronized (mQueriesViaComponentLock) { 713 mQueriesViaComponent.add(newPkgSetting.getAppId(), 714 existingSetting.getAppId()); 715 } 716 } 717 if (canQueryViaPackage(newPkg, existingPkg) 718 || canQueryAsInstaller(newPkgSetting, existingPkg) 719 || canQueryAsUpdateOwner(newPkgSetting, existingPkg)) { 720 synchronized (mQueriesViaPackageLock) { 721 mQueriesViaPackage.add(newPkgSetting.getAppId(), 722 existingSetting.getAppId()); 723 } 724 } 725 if (canQueryViaUsesLibrary(newPkg, existingPkg)) { 726 synchronized (mQueryableViaUsesLibraryLock) { 727 mQueryableViaUsesLibrary.add(newPkgSetting.getAppId(), 728 existingSetting.getAppId()); 729 } 730 } 731 } 732 // if either package instruments the other, mark both as visible to one another 733 if (newPkgSetting.getPkg() != null && existingSetting.getPkg() != null 734 && (pkgInstruments(newPkgSetting.getPkg(), existingSetting.getPkg()) 735 || pkgInstruments(existingSetting.getPkg(), newPkgSetting.getPkg()))) { 736 synchronized (mQueriesViaPackageLock) { 737 mQueriesViaPackage.add(newPkgSetting.getAppId(), existingSetting.getAppId()); 738 mQueriesViaPackage.add(existingSetting.getAppId(), newPkgSetting.getAppId()); 739 } 740 } 741 } 742 743 int existingSize = existingSettings.size(); 744 ArrayMap<String, AndroidPackage> existingPkgs = new ArrayMap<>(existingSize); 745 for (int index = 0; index < existingSize; index++) { 746 PackageStateInternal pkgSetting = existingSettings.valueAt(index); 747 if (pkgSetting.getPkg() != null) { 748 existingPkgs.put(pkgSetting.getPackageName(), pkgSetting.getPkg()); 749 } 750 } 751 752 ArraySet<String> changedPackages = 753 mOverlayReferenceMapper.addPkg(newPkgSetting.getPkg(), existingPkgs); 754 755 mFeatureConfig.updatePackageState(newPkgSetting, false /*removed*/); 756 757 return changedPackages; 758 } 759 removeAppIdFromVisibilityCache(int appId)760 private void removeAppIdFromVisibilityCache(int appId) { 761 synchronized (mCacheLock) { 762 for (int i = 0; i < mShouldFilterCache.size(); i++) { 763 if (UserHandle.getAppId(mShouldFilterCache.keyAt(i)) == appId) { 764 mShouldFilterCache.removeAt(i); 765 // The key was deleted so the list of keys has shifted left. That means i 766 // is now pointing at the next key to be examined. The decrement here and 767 // the loop increment together mean that i will be unchanged in the need 768 // iteration and will correctly point to the next key to be examined. 769 i--; 770 } 771 } 772 } 773 } 774 updateEntireShouldFilterCache(Computer snapshot, int subjectUserId)775 private void updateEntireShouldFilterCache(Computer snapshot, int subjectUserId) { 776 final ArrayMap<String, ? extends PackageStateInternal> settings = 777 snapshot.getPackageStates(); 778 final UserInfo[] users = snapshot.getUserInfos(); 779 int userId = USER_NULL; 780 for (int u = 0; u < users.length; u++) { 781 if (subjectUserId == users[u].id) { 782 userId = subjectUserId; 783 break; 784 } 785 } 786 if (userId == USER_NULL) { 787 Slog.e(TAG, "We encountered a new user that isn't a member of known users, " 788 + "updating the whole cache"); 789 userId = USER_ALL; 790 } 791 updateEntireShouldFilterCacheInner(snapshot, settings, users, userId); 792 793 onChanged(); 794 } 795 updateEntireShouldFilterCacheInner(Computer snapshot, ArrayMap<String, ? extends PackageStateInternal> settings, UserInfo[] users, int subjectUserId)796 private void updateEntireShouldFilterCacheInner(Computer snapshot, 797 ArrayMap<String, ? extends PackageStateInternal> settings, 798 UserInfo[] users, 799 int subjectUserId) { 800 synchronized (mCacheLock) { 801 if (subjectUserId == USER_ALL) { 802 mShouldFilterCache.clear(); 803 } 804 mShouldFilterCache.setCapacity(users.length * settings.size()); 805 for (int i = settings.size() - 1; i >= 0; i--) { 806 updateShouldFilterCacheForPackage(snapshot, 807 null /*skipPackage*/, settings.valueAt(i), settings, users, 808 subjectUserId, i); 809 } 810 } 811 } 812 updateEntireShouldFilterCacheAsync(PackageManagerInternal pmInternal, int reason)813 private void updateEntireShouldFilterCacheAsync(PackageManagerInternal pmInternal, int reason) { 814 updateEntireShouldFilterCacheAsync(pmInternal, CACHE_REBUILD_DELAY_MIN_MS, reason); 815 } 816 updateEntireShouldFilterCacheAsync(PackageManagerInternal pmInternal, long delayMs, int reason)817 private void updateEntireShouldFilterCacheAsync(PackageManagerInternal pmInternal, 818 long delayMs, int reason) { 819 mHandler.postDelayed(() -> { 820 if (!mCacheValid.compareAndSet(CACHE_INVALID, CACHE_VALID)) { 821 // Cache is already valid. 822 return; 823 } 824 825 final long currentTimeUs = SystemClock.currentTimeMicro(); 826 final ArrayMap<String, AndroidPackage> packagesCache = new ArrayMap<>(); 827 final UserInfo[][] usersRef = new UserInfo[1][]; 828 final Computer snapshot = (Computer) pmInternal.snapshot(); 829 final ArrayMap<String, ? extends PackageStateInternal> settings = 830 snapshot.getPackageStates(); 831 final UserInfo[] users = snapshot.getUserInfos(); 832 833 packagesCache.ensureCapacity(settings.size()); 834 usersRef[0] = users; 835 // store away the references to the immutable packages, since settings are retained 836 // during updates. 837 for (int i = 0, max = settings.size(); i < max; i++) { 838 final AndroidPackage pkg = settings.valueAt(i).getPkg(); 839 packagesCache.put(settings.keyAt(i), pkg); 840 } 841 842 updateEntireShouldFilterCacheInner(snapshot, settings, usersRef[0], USER_ALL); 843 logCacheRebuilt(reason, SystemClock.currentTimeMicro() - currentTimeUs, 844 users.length, settings.size()); 845 846 if (!mCacheValid.compareAndSet(CACHE_VALID, CACHE_VALID)) { 847 Slog.i(TAG, "Cache invalidated while building, retrying."); 848 updateEntireShouldFilterCacheAsync(pmInternal, 849 Math.min(delayMs * 2, CACHE_REBUILD_DELAY_MAX_MS), reason); 850 return; 851 } 852 853 synchronized (mImplicitlyQueryableLock) { 854 if (mNeedToUpdateCacheForImplicitAccess) { 855 updateShouldFilterCacheForImplicitAccess(); 856 mNeedToUpdateCacheForImplicitAccess = false; 857 } 858 mCacheReady = true; 859 } 860 861 onChanged(); 862 }, delayMs); 863 } 864 onUserCreated(Computer snapshot, int newUserId)865 public void onUserCreated(Computer snapshot, int newUserId) { 866 if (!mCacheReady) { 867 return; 868 } 869 final long currentTimeUs = SystemClock.currentTimeMicro(); 870 updateEntireShouldFilterCache(snapshot, newUserId); 871 logCacheRebuilt( 872 PACKAGE_MANAGER_APPS_FILTER_CACHE_BUILD_REPORTED__EVENT_TYPE__USER_CREATED, 873 SystemClock.currentTimeMicro() - currentTimeUs, 874 snapshot.getUserInfos().length, 875 snapshot.getPackageStates().size()); 876 } 877 onUserDeleted(Computer snapshot, @UserIdInt int userId)878 public void onUserDeleted(Computer snapshot, @UserIdInt int userId) { 879 if (!mCacheReady) { 880 return; 881 } 882 final long currentTimeUs = SystemClock.currentTimeMicro(); 883 removeShouldFilterCacheForUser(userId); 884 onChanged(); 885 logCacheRebuilt( 886 PACKAGE_MANAGER_APPS_FILTER_CACHE_BUILD_REPORTED__EVENT_TYPE__USER_DELETED, 887 SystemClock.currentTimeMicro() - currentTimeUs, 888 snapshot.getUserInfos().length, 889 snapshot.getPackageStates().size()); 890 } 891 892 @GuardedBy("mImplicitlyQueryableLock") updateShouldFilterCacheForImplicitAccess()893 private void updateShouldFilterCacheForImplicitAccess() { 894 updateShouldFilterCacheForImplicitAccess(mRetainedImplicitlyQueryable); 895 updateShouldFilterCacheForImplicitAccess(mImplicitlyQueryable); 896 } 897 updateShouldFilterCacheForImplicitAccess( WatchedSparseSetArray<Integer> queriesMap)898 private void updateShouldFilterCacheForImplicitAccess( 899 WatchedSparseSetArray<Integer> queriesMap) { 900 synchronized (mCacheLock) { 901 for (int i = 0; i < queriesMap.size(); i++) { 902 Integer callingUid = queriesMap.keyAt(i); 903 ArraySet<Integer> targetUids = queriesMap.get(callingUid); 904 for (Integer targetUid : targetUids) { 905 mShouldFilterCache.put(callingUid, targetUid, false); 906 } 907 } 908 } 909 } 910 updateShouldFilterCacheForPackage(Computer snapshot, String packageName)911 private void updateShouldFilterCacheForPackage(Computer snapshot, 912 String packageName) { 913 if (!mCacheReady) { 914 return; 915 } 916 final ArrayMap<String, ? extends PackageStateInternal> settings = 917 snapshot.getPackageStates(); 918 final UserInfo[] users = snapshot.getUserInfos(); 919 synchronized (mCacheLock) { 920 updateShouldFilterCacheForPackage(snapshot, null /* skipPackage */, 921 settings.get(packageName), settings, users, USER_ALL, 922 settings.size() /*maxIndex*/); 923 } 924 onChanged(); 925 } 926 927 @GuardedBy("mCacheLock") updateShouldFilterCacheForPackage(Computer snapshot, @Nullable String skipPackageName, PackageStateInternal subjectSetting, ArrayMap<String, ? extends PackageStateInternal> allSettings, UserInfo[] allUsers, int subjectUserId, int maxIndex)928 private void updateShouldFilterCacheForPackage(Computer snapshot, 929 @Nullable String skipPackageName, PackageStateInternal subjectSetting, ArrayMap<String, 930 ? extends PackageStateInternal> allSettings, UserInfo[] allUsers, int subjectUserId, 931 int maxIndex) { 932 for (int i = Math.min(maxIndex, allSettings.size() - 1); i >= 0; i--) { 933 PackageStateInternal otherSetting = allSettings.valueAt(i); 934 if (subjectSetting.getAppId() == otherSetting.getAppId()) { 935 continue; 936 } 937 //noinspection StringEquality 938 if (subjectSetting.getPackageName() == skipPackageName || otherSetting.getPackageName() 939 == skipPackageName) { 940 continue; 941 } 942 if (subjectUserId == USER_ALL) { 943 for (int su = 0; su < allUsers.length; su++) { 944 updateShouldFilterCacheForUser(snapshot, subjectSetting, allUsers, otherSetting, 945 allUsers[su].id); 946 } 947 } else { 948 updateShouldFilterCacheForUser(snapshot, subjectSetting, allUsers, otherSetting, 949 subjectUserId); 950 } 951 } 952 } 953 954 @GuardedBy("mCacheLock") updateShouldFilterCacheForUser(Computer snapshot, PackageStateInternal subjectSetting, UserInfo[] allUsers, PackageStateInternal otherSetting, int subjectUserId)955 private void updateShouldFilterCacheForUser(Computer snapshot, 956 PackageStateInternal subjectSetting, UserInfo[] allUsers, 957 PackageStateInternal otherSetting, int subjectUserId) { 958 for (int ou = 0; ou < allUsers.length; ou++) { 959 int otherUser = allUsers[ou].id; 960 int subjectUid = UserHandle.getUid(subjectUserId, subjectSetting.getAppId()); 961 int otherUid = UserHandle.getUid(otherUser, otherSetting.getAppId()); 962 final boolean shouldFilterSubjectToOther = shouldFilterApplicationInternal(snapshot, 963 subjectUid, subjectSetting, otherSetting, otherUser); 964 final boolean shouldFilterOtherToSubject = shouldFilterApplicationInternal(snapshot, 965 otherUid, otherSetting, subjectSetting, subjectUserId); 966 mShouldFilterCache.put(subjectUid, otherUid, shouldFilterSubjectToOther); 967 mShouldFilterCache.put(otherUid, subjectUid, shouldFilterOtherToSubject); 968 } 969 } 970 removeShouldFilterCacheForUser(int userId)971 private void removeShouldFilterCacheForUser(int userId) { 972 synchronized (mCacheLock) { 973 // Sorted uids with the ascending order 974 final int[] cacheUids = mShouldFilterCache.keys(); 975 final int size = cacheUids.length; 976 int pos = Arrays.binarySearch(cacheUids, UserHandle.getUid(userId, 0)); 977 final int fromIndex = (pos >= 0 ? pos : ~pos); 978 if (fromIndex >= size || UserHandle.getUserId(cacheUids[fromIndex]) != userId) { 979 Slog.w(TAG, "Failed to remove should filter cache for user " + userId 980 + ", fromIndex=" + fromIndex); 981 return; 982 } 983 pos = Arrays.binarySearch(cacheUids, UserHandle.getUid(userId + 1, 0) - 1); 984 final int toIndex = (pos >= 0 ? pos + 1 : ~pos); 985 if (fromIndex >= toIndex || UserHandle.getUserId(cacheUids[toIndex - 1]) != userId) { 986 Slog.w(TAG, "Failed to remove should filter cache for user " + userId 987 + ", fromIndex=" + fromIndex + ", toIndex=" + toIndex); 988 return; 989 } 990 mShouldFilterCache.removeRange(fromIndex, toIndex); 991 mShouldFilterCache.compact(); 992 } 993 } 994 isSystemSigned(@onNull SigningDetails sysSigningDetails, PackageStateInternal pkgSetting)995 private static boolean isSystemSigned(@NonNull SigningDetails sysSigningDetails, 996 PackageStateInternal pkgSetting) { 997 return pkgSetting.isSystem() 998 && pkgSetting.getSigningDetails().signaturesMatchExactly(sysSigningDetails); 999 } 1000 collectProtectedBroadcasts( ArrayMap<String, ? extends PackageStateInternal> existingSettings, @Nullable String excludePackage)1001 private void collectProtectedBroadcasts( 1002 ArrayMap<String, ? extends PackageStateInternal> existingSettings, 1003 @Nullable String excludePackage) { 1004 synchronized (mProtectedBroadcastsLock) { 1005 mProtectedBroadcasts.clear(); 1006 for (int i = existingSettings.size() - 1; i >= 0; i--) { 1007 PackageStateInternal setting = existingSettings.valueAt(i); 1008 if (setting.getPkg() == null || setting.getPkg().getPackageName().equals( 1009 excludePackage)) { 1010 continue; 1011 } 1012 final List<String> protectedBroadcasts = setting.getPkg().getProtectedBroadcasts(); 1013 if (!protectedBroadcasts.isEmpty()) { 1014 mProtectedBroadcasts.addAll(protectedBroadcasts); 1015 } 1016 } 1017 } 1018 } 1019 1020 @Override isQueryableViaComponentWhenRequireRecompute( ArrayMap<String, ? extends PackageStateInternal> existingSettings, PackageStateInternal callingPkgSetting, ArraySet<PackageStateInternal> callingSharedPkgSettings, AndroidPackage targetPkg, int callingAppId, int targetAppId)1021 protected boolean isQueryableViaComponentWhenRequireRecompute( 1022 ArrayMap<String, ? extends PackageStateInternal> existingSettings, 1023 PackageStateInternal callingPkgSetting, 1024 ArraySet<PackageStateInternal> callingSharedPkgSettings, 1025 AndroidPackage targetPkg, 1026 int callingAppId, int targetAppId) { 1027 // Recompute the whole mQueriesViaComponent because mProtectedBroadcasts have changed 1028 recomputeComponentVisibility(existingSettings); 1029 return isQueryableViaComponent(callingAppId, targetAppId); 1030 } 1031 1032 /** 1033 * This method recomputes all component / intent-based visibility and is intended to match the 1034 * relevant logic of {@link #addPackageInternal(PackageStateInternal, ArrayMap)} 1035 */ recomputeComponentVisibility( ArrayMap<String, ? extends PackageStateInternal> existingSettings)1036 private void recomputeComponentVisibility( 1037 ArrayMap<String, ? extends PackageStateInternal> existingSettings) { 1038 final WatchedArraySet<String> protectedBroadcasts; 1039 final ArraySet<Integer> forceQueryable; 1040 synchronized (mProtectedBroadcastsLock) { 1041 protectedBroadcasts = new WatchedArraySet<String>(mProtectedBroadcasts); 1042 } 1043 synchronized (mForceQueryableLock) { 1044 forceQueryable = new ArraySet<Integer>(mForceQueryable.untrackedStorage()); 1045 } 1046 final ParallelComputeComponentVisibility computer = new ParallelComputeComponentVisibility( 1047 existingSettings, forceQueryable, protectedBroadcasts); 1048 SparseSetArray<Integer> queriesViaComponent = computer.execute(); 1049 synchronized (mQueriesViaComponentLock) { 1050 mQueriesViaComponent = new WatchedSparseSetArray<>(queriesViaComponent); 1051 mQueriesViaComponentSnapshot = new SnapshotCache.Auto<>( 1052 mQueriesViaComponent, mQueriesViaComponent, "AppsFilter.mQueriesViaComponent"); 1053 } 1054 1055 mQueriesViaComponentRequireRecompute.set(false); 1056 onChanged(); 1057 } 1058 1059 /** 1060 * Equivalent to calling {@link #addPackage(Computer, PackageStateInternal, boolean, boolean)} 1061 * with {@code isReplace} and {@code retainImplicitGrantOnReplace} equal to {@code false}. 1062 * 1063 * @see AppsFilterImpl#addPackage(Computer, PackageStateInternal, boolean, boolean) 1064 */ addPackage(Computer snapshot, PackageStateInternal newPkgSetting)1065 public void addPackage(Computer snapshot, PackageStateInternal newPkgSetting) { 1066 addPackage(snapshot, newPkgSetting, false /* isReplace */, 1067 false /* retainImplicitGrantOnReplace */); 1068 } 1069 1070 /** 1071 * Removes a package for consideration when filtering visibility between apps. 1072 * 1073 * @param setting the setting of the package being removed. 1074 */ removePackage(Computer snapshot, PackageStateInternal setting)1075 public void removePackage(Computer snapshot, PackageStateInternal setting) { 1076 final long currentTimeUs = SystemClock.currentTimeMicro(); 1077 removePackageInternal(snapshot, setting, 1078 false /* isReplace */, false /* retainImplicitGrantOnReplace */); 1079 logCacheUpdated( 1080 PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED__EVENT_TYPE__PACKAGE_DELETED, 1081 SystemClock.currentTimeMicro() - currentTimeUs, 1082 snapshot.getUserInfos().length, 1083 snapshot.getPackageStates().size(), 1084 setting.getAppId()); 1085 } 1086 1087 /** 1088 * Removes a package for consideration when filtering visibility between apps. 1089 * 1090 * @param setting the setting of the package being removed. 1091 * @param isReplace if the package is being replaced. 1092 * @param retainImplicitGrantOnReplace {@code true} to retain implicit grant access if 1093 * the package is being replaced. 1094 */ removePackageInternal(Computer snapshot, PackageStateInternal setting, boolean isReplace, boolean retainImplicitGrantOnReplace)1095 private void removePackageInternal(Computer snapshot, PackageStateInternal setting, 1096 boolean isReplace, boolean retainImplicitGrantOnReplace) { 1097 final ArraySet<String> additionalChangedPackages; 1098 final ArrayMap<String, ? extends PackageStateInternal> settings = 1099 snapshot.getPackageStates(); 1100 final UserInfo[] users = snapshot.getUserInfos(); 1101 final int userCount = users.length; 1102 if (!isReplace || !retainImplicitGrantOnReplace) { 1103 synchronized (mImplicitlyQueryableLock) { 1104 for (int u = 0; u < userCount; u++) { 1105 final int userId = users[u].id; 1106 final int removingUid = UserHandle.getUid(userId, setting.getAppId()); 1107 mImplicitlyQueryable.remove(removingUid); 1108 for (int i = mImplicitlyQueryable.size() - 1; i >= 0; i--) { 1109 mImplicitlyQueryable.remove(mImplicitlyQueryable.keyAt(i), 1110 removingUid); 1111 } 1112 1113 if (isReplace) { 1114 continue; 1115 } 1116 1117 mRetainedImplicitlyQueryable.remove(removingUid); 1118 for (int i = mRetainedImplicitlyQueryable.size() - 1; i >= 0; i--) { 1119 mRetainedImplicitlyQueryable.remove( 1120 mRetainedImplicitlyQueryable.keyAt(i), removingUid); 1121 } 1122 } 1123 } 1124 } 1125 1126 if (!mQueriesViaComponentRequireRecompute.get()) { 1127 synchronized (mQueriesViaComponentLock) { 1128 mQueriesViaComponent.remove(setting.getAppId()); 1129 for (int i = mQueriesViaComponent.size() - 1; i >= 0; i--) { 1130 mQueriesViaComponent.remove(mQueriesViaComponent.keyAt(i), setting.getAppId()); 1131 } 1132 } 1133 } 1134 1135 synchronized (mQueriesViaPackageLock) { 1136 mQueriesViaPackage.remove(setting.getAppId()); 1137 for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) { 1138 mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i), 1139 setting.getAppId()); 1140 } 1141 } 1142 1143 synchronized (mQueryableViaUsesLibraryLock) { 1144 mQueryableViaUsesLibrary.remove(setting.getAppId()); 1145 for (int i = mQueryableViaUsesLibrary.size() - 1; i >= 0; i--) { 1146 mQueryableViaUsesLibrary.remove(mQueryableViaUsesLibrary.keyAt(i), 1147 setting.getAppId()); 1148 } 1149 } 1150 1151 synchronized (mQueryableViaUsesPermissionLock) { 1152 if (setting.getPkg() != null && !setting.getPkg().getPermissions().isEmpty()) { 1153 for (ParsedPermission permission : setting.getPkg().getPermissions()) { 1154 String permissionName = permission.getName(); 1155 if (mPermissionToUids.containsKey(permissionName)) { 1156 mPermissionToUids.get(permissionName).remove(setting.getAppId()); 1157 if (mPermissionToUids.get(permissionName).isEmpty()) { 1158 mPermissionToUids.remove(permissionName); 1159 } 1160 } 1161 } 1162 } 1163 if (setting.getPkg() != null && !setting.getPkg().getUsesPermissions().isEmpty()) { 1164 for (ParsedUsesPermission usesPermission : setting.getPkg().getUsesPermissions()) { 1165 String usesPermissionName = usesPermission.getName(); 1166 if (mUsesPermissionToUids.containsKey(usesPermissionName)) { 1167 mUsesPermissionToUids.get(usesPermissionName).remove(setting.getAppId()); 1168 if (mUsesPermissionToUids.get(usesPermissionName).isEmpty()) { 1169 mUsesPermissionToUids.remove(usesPermissionName); 1170 } 1171 } 1172 } 1173 } 1174 mQueryableViaUsesPermission.remove(setting.getAppId()); 1175 } 1176 1177 synchronized (mForceQueryableLock) { 1178 mForceQueryable.remove(setting.getAppId()); 1179 } 1180 1181 boolean protectedBroadcastsChanged = false; 1182 synchronized (mProtectedBroadcastsLock) { 1183 if (setting.getPkg() != null 1184 && !setting.getPkg().getProtectedBroadcasts().isEmpty()) { 1185 final String removingPackageName = setting.getPkg().getPackageName(); 1186 final ArrayList<String> protectedBroadcasts = new ArrayList<>( 1187 mProtectedBroadcasts.untrackedStorage()); 1188 collectProtectedBroadcasts(settings, removingPackageName); 1189 for (int i = 0; i < protectedBroadcasts.size(); ++i) { 1190 if (!mProtectedBroadcasts.contains(protectedBroadcasts.get(i))) { 1191 protectedBroadcastsChanged = true; 1192 break; 1193 } 1194 } 1195 } 1196 } 1197 1198 if (protectedBroadcastsChanged) { 1199 mQueriesViaComponentRequireRecompute.set(true); 1200 } 1201 1202 additionalChangedPackages = mOverlayReferenceMapper.removePkg(setting.getPackageName()); 1203 mFeatureConfig.updatePackageState(setting, true /*removed*/); 1204 1205 // After removing all traces of the package, if it's part of a shared user, re-add other 1206 // shared user members to re-establish visibility between them and other packages. 1207 // NOTE: this must come after all removals from data structures but before we update the 1208 // cache 1209 final SharedUserApi sharedUserApi = setting.hasSharedUser() 1210 ? snapshot.getSharedUser(setting.getSharedUserAppId()) : null; 1211 if (sharedUserApi != null) { 1212 final ArraySet<? extends PackageStateInternal> sharedUserPackages = 1213 sharedUserApi.getPackageStates(); 1214 for (int i = sharedUserPackages.size() - 1; i >= 0; i--) { 1215 if (sharedUserPackages.valueAt(i) == setting) { 1216 continue; 1217 } 1218 addPackageInternal( 1219 sharedUserPackages.valueAt(i), settings); 1220 } 1221 } 1222 1223 if (mCacheReady) { 1224 removeAppIdFromVisibilityCache(setting.getAppId()); 1225 1226 if (sharedUserApi != null) { 1227 final ArraySet<? extends PackageStateInternal> sharedUserPackages = 1228 sharedUserApi.getPackageStates(); 1229 for (int i = sharedUserPackages.size() - 1; i >= 0; i--) { 1230 PackageStateInternal siblingSetting = 1231 sharedUserPackages.valueAt(i); 1232 if (siblingSetting == setting) { 1233 continue; 1234 } 1235 synchronized (mCacheLock) { 1236 updateShouldFilterCacheForPackage(snapshot, 1237 setting.getPackageName(), siblingSetting, settings, 1238 users, USER_ALL, settings.size()); 1239 } 1240 break; 1241 } 1242 } 1243 1244 if (additionalChangedPackages != null) { 1245 for (int index = 0; index < additionalChangedPackages.size(); index++) { 1246 String changedPackage = additionalChangedPackages.valueAt(index); 1247 PackageStateInternal changedPkgSetting = settings.get(changedPackage); 1248 if (changedPkgSetting == null) { 1249 // It's possible for the overlay mapper to know that an actor 1250 // package changed via an explicit reference, even if the actor 1251 // isn't installed, so skip if that's the case. 1252 continue; 1253 } 1254 synchronized (mCacheLock) { 1255 updateShouldFilterCacheForPackage(snapshot, null, changedPkgSetting, 1256 settings, users, USER_ALL, settings.size()); 1257 } 1258 } 1259 } 1260 } else { 1261 invalidateCache("removePackage: " + setting.getPackageName()); 1262 } 1263 onChanged(); 1264 } 1265 1266 /** Returns {@code true} if the source package instruments the target package. */ pkgInstruments( @onNull AndroidPackage source, @NonNull AndroidPackage target)1267 private static boolean pkgInstruments( 1268 @NonNull AndroidPackage source, @NonNull AndroidPackage target) { 1269 try { 1270 if (DEBUG_TRACING) { 1271 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "pkgInstruments"); 1272 } 1273 final String packageName = target.getPackageName(); 1274 final List<ParsedInstrumentation> inst = source.getInstrumentations(); 1275 for (int i = ArrayUtils.size(inst) - 1; i >= 0; i--) { 1276 if (Objects.equals(inst.get(i).getTargetPackage(), packageName)) { 1277 return true; 1278 } 1279 } 1280 return false; 1281 } finally { 1282 if (DEBUG_TRACING) { 1283 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 1284 } 1285 } 1286 } 1287 logCacheRebuilt(int eventId, long latency, int userCount, int packageCount)1288 private void logCacheRebuilt(int eventId, long latency, int userCount, int packageCount) { 1289 FrameworkStatsLog.write(PACKAGE_MANAGER_APPS_FILTER_CACHE_BUILD_REPORTED, 1290 eventId, latency, userCount, packageCount, mShouldFilterCache.size()); 1291 } 1292 logCacheUpdated(int eventId, long latency, int userCount, int packageCount, int appId)1293 private void logCacheUpdated(int eventId, long latency, int userCount, int packageCount, 1294 int appId) { 1295 if (!mCacheReady) { 1296 return; 1297 } 1298 FrameworkStatsLog.write(PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED, 1299 eventId, appId, latency, userCount, packageCount, mShouldFilterCache.size()); 1300 } 1301 } 1302