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