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