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