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