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