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