• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 
21 import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
22 import static com.android.server.pm.AppsFilterUtils.canQueryViaComponents;
23 import static com.android.server.pm.AppsFilterUtils.requestsQueryAllPackages;
24 
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.content.pm.SigningDetails;
28 import android.os.Binder;
29 import android.os.Handler;
30 import android.os.Process;
31 import android.os.Trace;
32 import android.os.UserHandle;
33 import android.text.TextUtils;
34 import android.util.ArrayMap;
35 import android.util.ArraySet;
36 import android.util.Slog;
37 import android.util.SparseArray;
38 
39 import com.android.internal.annotations.VisibleForTesting;
40 import com.android.internal.util.function.QuadFunction;
41 import com.android.server.om.OverlayReferenceMapper;
42 import com.android.server.pm.parsing.pkg.AndroidPackage;
43 import com.android.server.pm.pkg.PackageStateInternal;
44 import com.android.server.pm.snapshot.PackageDataSnapshot;
45 import com.android.server.utils.SnapshotCache;
46 import com.android.server.utils.Watched;
47 import com.android.server.utils.WatchedArrayList;
48 import com.android.server.utils.WatchedArrayMap;
49 import com.android.server.utils.WatchedArraySet;
50 import com.android.server.utils.WatchedSparseBooleanMatrix;
51 import com.android.server.utils.WatchedSparseSetArray;
52 
53 import java.io.PrintWriter;
54 import java.util.Arrays;
55 import java.util.Collection;
56 import java.util.Objects;
57 import java.util.concurrent.atomic.AtomicBoolean;
58 
59 /**
60  * AppsFilter is the entity responsible for filtering visibility between apps based on declarations
61  * in their manifests. This class implements the unlocked, read-only methods of AppsFilter.
62  * See {@link AppsFilterImpl} for the write methods that updates the internal structures.
63  */
64 public abstract class AppsFilterBase implements AppsFilterSnapshot {
65     protected static final String TAG = "AppsFilter";
66 
67     // Logs all filtering instead of enforcing
68     protected static final boolean DEBUG_ALLOW_ALL = false;
69     protected static final boolean DEBUG_LOGGING = false;
70     public static final boolean DEBUG_TRACING = false;
71 
72     // Allow some time for cache rebuilds.
73     protected static final int CACHE_REBUILD_DELAY_MIN_MS = 10000;
74     // With each new rebuild the delay doubles until it reaches max delay.
75     protected static final int CACHE_REBUILD_DELAY_MAX_MS = 10000;
76 
77     /**
78      * This contains a list of app UIDs that are implicitly queryable because another app explicitly
79      * interacted with it. For example, if application A starts a service in application B,
80      * application B is implicitly allowed to query for application A; regardless of any manifest
81      * entries.
82      */
83     @NonNull
84     @Watched
85     protected WatchedSparseSetArray<Integer> mImplicitlyQueryable;
86     @NonNull
87     protected SnapshotCache<WatchedSparseSetArray<Integer>> mImplicitQueryableSnapshot;
88 
89     /**
90      * This contains a list of app UIDs that are implicitly queryable because another app explicitly
91      * interacted with it, but could keep across package updates. For example, if application A
92      * grants persistable uri permission to application B; regardless of any manifest entries.
93      */
94     @NonNull
95     @Watched
96     protected WatchedSparseSetArray<Integer> mRetainedImplicitlyQueryable;
97     @NonNull
98     protected SnapshotCache<WatchedSparseSetArray<Integer>> mRetainedImplicitlyQueryableSnapshot;
99 
100     /**
101      * A mapping from the set of App IDs that query other App IDs via package name to the
102      * list of packages that they can see.
103      */
104     @NonNull
105     @Watched
106     protected WatchedSparseSetArray<Integer> mQueriesViaPackage;
107     @NonNull
108     protected SnapshotCache<WatchedSparseSetArray<Integer>> mQueriesViaPackageSnapshot;
109 
110     /**
111      * A mapping from the set of App IDs that query others via component match to the list
112      * of packages that the they resolve to.
113      */
114     @NonNull
115     @Watched
116     protected WatchedSparseSetArray<Integer> mQueriesViaComponent;
117     @NonNull
118     protected SnapshotCache<WatchedSparseSetArray<Integer>> mQueriesViaComponentSnapshot;
119 
120     /**
121      * A mapping from the set of App IDs that query other App IDs via library name to the
122      * list of packages that they can see.
123      */
124     @NonNull
125     @Watched
126     protected WatchedSparseSetArray<Integer> mQueryableViaUsesLibrary;
127     @NonNull
128     protected SnapshotCache<WatchedSparseSetArray<Integer>> mQueryableViaUsesLibrarySnapshot;
129 
130     /**
131      * Handler for running reasonably short background tasks such as building the initial
132      * visibility cache.
133      */
134     protected Handler mBackgroundHandler;
135 
136     /**
137      * Pending full recompute of mQueriesViaComponent. Occurs when a package adds a new set of
138      * protected broadcast. This in turn invalidates all prior additions and require a very
139      * computationally expensive recomputing.
140      * Full recompute is done lazily at the point when we use mQueriesViaComponent to filter apps.
141      */
142     protected AtomicBoolean mQueriesViaComponentRequireRecompute = new AtomicBoolean(false);
143 
144     /**
145      * A set of App IDs that are always queryable by any package, regardless of their manifest
146      * content.
147      */
148     @NonNull
149     @Watched
150     protected WatchedArraySet<Integer> mForceQueryable;
151     @NonNull
152     protected SnapshotCache<WatchedArraySet<Integer>> mForceQueryableSnapshot;
153 
154     /**
155      * The set of package names provided by the device that should be force queryable regardless of
156      * their manifest contents.
157      */
158     @NonNull
159     protected String[] mForceQueryableByDevicePackageNames;
160     @NonNull
161     /** True if all system apps should be made queryable by default. */
162     protected boolean mSystemAppsQueryable;
163     @NonNull
164     protected FeatureConfig mFeatureConfig;
165     @NonNull
166     protected OverlayReferenceMapper mOverlayReferenceMapper;
167     @Nullable
168     protected SigningDetails mSystemSigningDetails;
169 
170     @NonNull
171     @Watched
172     protected WatchedArrayList<String> mProtectedBroadcasts;
173     @NonNull
174     protected SnapshotCache<WatchedArrayList<String>> mProtectedBroadcastsSnapshot;
175 
176     /**
177      * This structure maps uid -> uid and indicates whether access from the first should be
178      * filtered to the second. It's essentially a cache of the
179      * {@link #shouldFilterApplicationInternal(PackageDataSnapshot, int, Object,
180      * PackageStateInternal, int)} call.
181      * NOTE: It can only be relied upon after the system is ready to avoid unnecessary update on
182      * initial scam and is empty until {@link #mCacheReady} is true.
183      */
184     @NonNull
185     @Watched
186     protected WatchedSparseBooleanMatrix mShouldFilterCache;
187     @NonNull
188     protected SnapshotCache<WatchedSparseBooleanMatrix> mShouldFilterCacheSnapshot;
189 
190     protected volatile boolean mCacheReady = false;
191 
192     protected static final boolean CACHE_VALID = true;
193     protected static final boolean CACHE_INVALID = false;
194     protected AtomicBoolean mCacheValid = new AtomicBoolean(CACHE_INVALID);
195 
isForceQueryable(int callingAppId)196     protected boolean isForceQueryable(int callingAppId) {
197         return mForceQueryable.contains(callingAppId);
198     }
199 
isQueryableViaPackage(int callingAppId, int targetAppId)200     protected boolean isQueryableViaPackage(int callingAppId, int targetAppId) {
201         return mQueriesViaPackage.contains(callingAppId, targetAppId);
202     }
203 
isQueryableViaComponent(int callingAppId, int targetAppId)204     protected boolean isQueryableViaComponent(int callingAppId, int targetAppId) {
205         return mQueriesViaComponent.contains(callingAppId, targetAppId);
206     }
207 
isImplicitlyQueryable(int callingUid, int targetUid)208     protected boolean isImplicitlyQueryable(int callingUid, int targetUid) {
209         return mImplicitlyQueryable.contains(callingUid, targetUid);
210     }
211 
isRetainedImplicitlyQueryable(int callingUid, int targetUid)212     protected boolean isRetainedImplicitlyQueryable(int callingUid, int targetUid) {
213         return mRetainedImplicitlyQueryable.contains(callingUid, targetUid);
214     }
215 
isQueryableViaUsesLibrary(int callingAppId, int targetAppId)216     protected boolean isQueryableViaUsesLibrary(int callingAppId, int targetAppId) {
217         return mQueryableViaUsesLibrary.contains(callingAppId, targetAppId);
218     }
219 
isQueryableViaComponentWhenRequireRecompute( ArrayMap<String, ? extends PackageStateInternal> existingSettings, PackageStateInternal callingPkgSetting, ArraySet<PackageStateInternal> callingSharedPkgSettings, AndroidPackage targetPkg, int callingAppId, int targetAppId)220     protected boolean isQueryableViaComponentWhenRequireRecompute(
221             ArrayMap<String, ? extends PackageStateInternal> existingSettings,
222             PackageStateInternal callingPkgSetting,
223             ArraySet<PackageStateInternal> callingSharedPkgSettings,
224             AndroidPackage targetPkg,
225             int callingAppId, int targetAppId) {
226         // Do no recompute or use mQueriesViaComponent if it's stale in snapshot
227         // Since we know we are in the snapshot, no need to acquire mLock because
228         // mProtectedBroadcasts will not change
229         if (callingPkgSetting != null) {
230             if (callingPkgSetting.getPkg() != null
231                     && canQueryViaComponents(callingPkgSetting.getPkg(), targetPkg,
232                     mProtectedBroadcasts)) {
233                 return true;
234             }
235         } else {
236             for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) {
237                 final AndroidPackage pkg =
238                         callingSharedPkgSettings.valueAt(i).getPkg();
239                 if (pkg != null && canQueryViaComponents(pkg, targetPkg,
240                         mProtectedBroadcasts)) {
241                     return true;
242                 }
243             }
244         }
245         return false;
246     }
247 
248     /**
249      * See {@link AppsFilterSnapshot#getVisibilityAllowList(PackageDataSnapshot,
250      * PackageStateInternal, int[], ArrayMap)}
251      */
252     @Override
253     @Nullable
getVisibilityAllowList(PackageDataSnapshot snapshot, PackageStateInternal setting, int[] users, ArrayMap<String, ? extends PackageStateInternal> existingSettings)254     public SparseArray<int[]> getVisibilityAllowList(PackageDataSnapshot snapshot,
255             PackageStateInternal setting, int[] users,
256             ArrayMap<String, ? extends PackageStateInternal> existingSettings) {
257         if (isForceQueryable(setting.getAppId())) {
258             return null;
259         }
260         // let's reserve max memory to limit the number of allocations
261         SparseArray<int[]> result = new SparseArray<>(users.length);
262         for (int u = 0; u < users.length; u++) {
263             final int userId = users[u];
264             int[] appIds = new int[existingSettings.size()];
265             int[] buffer = null;
266             int allowListSize = 0;
267             for (int i = existingSettings.size() - 1; i >= 0; i--) {
268                 final PackageStateInternal existingSetting = existingSettings.valueAt(i);
269                 final int existingAppId = existingSetting.getAppId();
270                 if (existingAppId < Process.FIRST_APPLICATION_UID) {
271                     continue;
272                 }
273                 final int loc = Arrays.binarySearch(appIds, 0, allowListSize, existingAppId);
274                 if (loc >= 0) {
275                     continue;
276                 }
277                 final int existingUid = UserHandle.getUid(userId, existingAppId);
278                 if (!shouldFilterApplication(snapshot, existingUid, existingSetting, setting,
279                         userId)) {
280                     if (buffer == null) {
281                         buffer = new int[appIds.length];
282                     }
283                     final int insert = ~loc;
284                     System.arraycopy(appIds, insert, buffer, 0, allowListSize - insert);
285                     appIds[insert] = existingAppId;
286                     System.arraycopy(buffer, 0, appIds, insert + 1, allowListSize - insert);
287                     allowListSize++;
288                 }
289             }
290             result.put(userId, Arrays.copyOf(appIds, allowListSize));
291         }
292         return result;
293     }
294 
295     /**
296      * This api does type conversion on the <existingSettings> parameter.
297      */
298     @VisibleForTesting(visibility = PRIVATE)
299     @Nullable
getVisibilityAllowList(PackageDataSnapshot snapshot, PackageStateInternal setting, int[] users, WatchedArrayMap<String, ? extends PackageStateInternal> existingSettings)300     SparseArray<int[]> getVisibilityAllowList(PackageDataSnapshot snapshot,
301             PackageStateInternal setting, int[] users,
302             WatchedArrayMap<String, ? extends PackageStateInternal> existingSettings) {
303         return getVisibilityAllowList(snapshot, setting, users,
304                 existingSettings.untrackedStorage());
305     }
306 
307     /**
308      * See
309      * {@link AppsFilterSnapshot#shouldFilterApplication(PackageDataSnapshot, int, Object,
310      * PackageStateInternal, int)}
311      */
312     @Override
shouldFilterApplication(PackageDataSnapshot snapshot, int callingUid, @Nullable Object callingSetting, PackageStateInternal targetPkgSetting, int userId)313     public boolean shouldFilterApplication(PackageDataSnapshot snapshot, int callingUid,
314             @Nullable Object callingSetting, PackageStateInternal targetPkgSetting, int userId) {
315         if (DEBUG_TRACING) {
316             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplication");
317         }
318         try {
319             int callingAppId = UserHandle.getAppId(callingUid);
320             if (callingAppId < Process.FIRST_APPLICATION_UID
321                     || targetPkgSetting.getAppId() < Process.FIRST_APPLICATION_UID
322                     || callingAppId == targetPkgSetting.getAppId()) {
323                 return false;
324             } else if (Process.isSdkSandboxUid(callingAppId)) {
325                 final int targetAppId = targetPkgSetting.getAppId();
326                 final int targetUid = UserHandle.getUid(userId, targetAppId);
327                 // we only allow sdk sandbox processes access to forcequeryable packages
328                 return !isForceQueryable(targetPkgSetting.getAppId())
329                       && !isImplicitlyQueryable(callingUid, targetUid);
330             }
331             if (mCacheReady) { // use cache
332                 if (!shouldFilterApplicationUsingCache(callingUid,
333                         targetPkgSetting.getAppId(),
334                         userId)) {
335                     return false;
336                 }
337             } else {
338                 if (!shouldFilterApplicationInternal(snapshot,
339                         callingUid, callingSetting, targetPkgSetting, userId)) {
340                     return false;
341                 }
342             }
343             if (DEBUG_LOGGING || mFeatureConfig.isLoggingEnabled(callingAppId)) {
344                 log(callingSetting, targetPkgSetting, "BLOCKED");
345             }
346             return !DEBUG_ALLOW_ALL;
347         } finally {
348             if (DEBUG_TRACING) {
349                 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
350             }
351         }
352     }
353 
shouldFilterApplicationUsingCache(int callingUid, int appId, int userId)354     protected boolean shouldFilterApplicationUsingCache(int callingUid, int appId, int userId) {
355         final int callingIndex = mShouldFilterCache.indexOfKey(callingUid);
356         if (callingIndex < 0) {
357             Slog.wtf(TAG, "Encountered calling uid with no cached rules: "
358                     + callingUid);
359             return true;
360         }
361         final int targetUid = UserHandle.getUid(userId, appId);
362         final int targetIndex = mShouldFilterCache.indexOfKey(targetUid);
363         if (targetIndex < 0) {
364             Slog.w(TAG, "Encountered calling -> target with no cached rules: "
365                     + callingUid + " -> " + targetUid);
366             return true;
367         }
368         return mShouldFilterCache.valueAt(callingIndex, targetIndex);
369     }
370 
shouldFilterApplicationInternal(PackageDataSnapshot snapshot, int callingUid, Object callingSetting, PackageStateInternal targetPkgSetting, int targetUserId)371     protected boolean shouldFilterApplicationInternal(PackageDataSnapshot snapshot, int callingUid,
372             Object callingSetting, PackageStateInternal targetPkgSetting, int targetUserId) {
373         if (DEBUG_TRACING) {
374             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplicationInternal");
375         }
376         try {
377             final boolean featureEnabled = mFeatureConfig.isGloballyEnabled();
378             if (!featureEnabled) {
379                 if (DEBUG_LOGGING) {
380                     Slog.d(TAG, "filtering disabled; skipped");
381                 }
382                 return false;
383             }
384             if (callingSetting == null) {
385                 Slog.wtf(TAG, "No setting found for non system uid " + callingUid);
386                 return true;
387             }
388             final PackageStateInternal callingPkgSetting;
389             if (DEBUG_TRACING) {
390                 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "callingSetting instanceof");
391             }
392             final ArraySet<PackageStateInternal> callingSharedPkgSettings = new ArraySet<>();
393 
394             if (callingSetting instanceof PackageStateInternal) {
395                 final PackageStateInternal packageState = (PackageStateInternal) callingSetting;
396                 if (packageState.hasSharedUser()) {
397                     callingPkgSetting = null;
398                     callingSharedPkgSettings.addAll(getSharedUserPackages(
399                             packageState.getSharedUserAppId(), snapshot.getAllSharedUsers()));
400 
401                 } else {
402                     callingPkgSetting = packageState;
403                 }
404             } else {
405                 callingPkgSetting = null;
406                 callingSharedPkgSettings.addAll(
407                         ((SharedUserSetting) callingSetting).getPackageStates());
408             }
409             if (DEBUG_TRACING) {
410                 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
411             }
412 
413             if (callingPkgSetting != null) {
414                 if (callingPkgSetting.getPkg() != null
415                         && !mFeatureConfig.packageIsEnabled(callingPkgSetting.getPkg())) {
416                     if (DEBUG_LOGGING) {
417                         log(callingSetting, targetPkgSetting, "DISABLED");
418                     }
419                     return false;
420                 }
421             } else {
422                 for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) {
423                     final AndroidPackage pkg = callingSharedPkgSettings.valueAt(i).getPkg();
424                     if (pkg != null && !mFeatureConfig.packageIsEnabled(pkg)) {
425                         if (DEBUG_LOGGING) {
426                             log(callingSetting, targetPkgSetting, "DISABLED");
427                         }
428                         return false;
429                     }
430                 }
431             }
432 
433             if (DEBUG_TRACING) {
434                 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "getAppId");
435             }
436             final int callingAppId;
437             if (callingPkgSetting != null) {
438                 callingAppId = callingPkgSetting.getAppId();
439             } else {
440                 // all should be the same
441                 callingAppId = callingSharedPkgSettings.valueAt(0).getAppId();
442             }
443             final int targetAppId = targetPkgSetting.getAppId();
444             if (DEBUG_TRACING) {
445                 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
446             }
447             if (callingAppId == targetAppId) {
448                 if (DEBUG_LOGGING) {
449                     log(callingSetting, targetPkgSetting, "same app id");
450                 }
451                 return false;
452             }
453 
454             try {
455                 if (DEBUG_TRACING) {
456                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "requestsQueryAllPackages");
457                 }
458                 if (callingPkgSetting != null) {
459                     if (callingPkgSetting.getPkg() != null
460                             && requestsQueryAllPackages(callingPkgSetting.getPkg())) {
461                         return false;
462                     }
463                 } else {
464                     for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) {
465                         AndroidPackage pkg = callingSharedPkgSettings.valueAt(i).getPkg();
466                         if (pkg != null && requestsQueryAllPackages(pkg)) {
467                             return false;
468                         }
469                     }
470                 }
471             } finally {
472                 if (DEBUG_TRACING) {
473                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
474                 }
475             }
476 
477             // This package isn't technically installed and won't be written to settings, so we can
478             // treat it as filtered until it's available again.
479             final AndroidPackage targetPkg = targetPkgSetting.getPkg();
480             if (targetPkg == null) {
481                 if (DEBUG_LOGGING) {
482                     Slog.wtf(TAG, "shouldFilterApplication: " + "targetPkg is null");
483                 }
484                 return true;
485             }
486             if (targetPkg.isStaticSharedLibrary()) {
487                 // not an app, this filtering takes place at a higher level
488                 return false;
489             }
490 
491             try {
492                 if (DEBUG_TRACING) {
493                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mForceQueryable");
494                 }
495                 if (isForceQueryable(targetAppId)) {
496                     if (DEBUG_LOGGING) {
497                         log(callingSetting, targetPkgSetting, "force queryable");
498                     }
499                     return false;
500                 }
501             } finally {
502                 if (DEBUG_TRACING) {
503                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
504                 }
505             }
506             try {
507                 if (DEBUG_TRACING) {
508                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueriesViaPackage");
509                 }
510                 if (isQueryableViaPackage(callingAppId, targetAppId)) {
511                     if (DEBUG_LOGGING) {
512                         log(callingSetting, targetPkgSetting, "queries package");
513                     }
514                     return false;
515                 }
516             } finally {
517                 if (DEBUG_TRACING) {
518                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
519                 }
520             }
521             try {
522                 if (DEBUG_TRACING) {
523                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueriesViaComponent");
524                 }
525                 if (!mQueriesViaComponentRequireRecompute.get()) {
526                     if (isQueryableViaComponent(callingAppId, targetAppId)) {
527                         if (DEBUG_LOGGING) {
528                             log(callingSetting, targetPkgSetting, "queries component");
529                         }
530                         return false;
531                     }
532                 } else { // mQueriesViaComponent is stale
533                     if (isQueryableViaComponentWhenRequireRecompute(snapshot.getPackageStates(),
534                             callingPkgSetting, callingSharedPkgSettings, targetPkg,
535                             callingAppId, targetAppId)) {
536                         if (DEBUG_LOGGING) {
537                             log(callingSetting, targetPkgSetting, "queries component");
538                         }
539                         return false;
540                     }
541                 }
542             } finally {
543                 if (DEBUG_TRACING) {
544                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
545                 }
546             }
547 
548             try {
549                 if (DEBUG_TRACING) {
550                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mImplicitlyQueryable");
551                 }
552                 final int targetUid = UserHandle.getUid(targetUserId, targetAppId);
553                 if (isImplicitlyQueryable(callingUid, targetUid)) {
554                     if (DEBUG_LOGGING) {
555                         log(callingSetting, targetPkgSetting, "implicitly queryable for user");
556                     }
557                     return false;
558                 }
559             } finally {
560                 if (DEBUG_TRACING) {
561                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
562                 }
563             }
564 
565             try {
566                 if (DEBUG_TRACING) {
567                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mRetainedImplicitlyQueryable");
568                 }
569                 final int targetUid = UserHandle.getUid(targetUserId, targetAppId);
570                 if (isRetainedImplicitlyQueryable(callingUid, targetUid)) {
571                     if (DEBUG_LOGGING) {
572                         log(callingSetting, targetPkgSetting,
573                                 "retained implicitly queryable for user");
574                     }
575                     return false;
576                 }
577             } finally {
578                 if (DEBUG_TRACING) {
579                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
580                 }
581             }
582 
583             try {
584                 if (DEBUG_TRACING) {
585                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mOverlayReferenceMapper");
586                 }
587                 final String targetName = targetPkg.getPackageName();
588                 if (!callingSharedPkgSettings.isEmpty()) {
589                     int size = callingSharedPkgSettings.size();
590                     for (int index = 0; index < size; index++) {
591                         PackageStateInternal pkgSetting = callingSharedPkgSettings.valueAt(index);
592                         if (mOverlayReferenceMapper.isValidActor(targetName,
593                                 pkgSetting.getPackageName())) {
594                             if (DEBUG_LOGGING) {
595                                 log(callingPkgSetting, targetPkgSetting,
596                                         "matches shared user of package that acts on target of "
597                                                 + "overlay");
598                             }
599                             return false;
600                         }
601                     }
602                 } else {
603                     if (mOverlayReferenceMapper.isValidActor(targetName,
604                             callingPkgSetting.getPackageName())) {
605                         if (DEBUG_LOGGING) {
606                             log(callingPkgSetting, targetPkgSetting, "acts on target of overlay");
607                         }
608                         return false;
609                     }
610                 }
611             } finally {
612                 if (DEBUG_TRACING) {
613                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
614                 }
615             }
616 
617             try {
618                 if (DEBUG_TRACING) {
619                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueryableViaUsesLibrary");
620                 }
621                 if (isQueryableViaUsesLibrary(callingAppId, targetAppId)) {
622                     if (DEBUG_LOGGING) {
623                         log(callingSetting, targetPkgSetting, "queryable for library users");
624                     }
625                     return false;
626                 }
627             } finally {
628                 if (DEBUG_TRACING) {
629                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
630                 }
631             }
632 
633             return true;
634         } finally {
635             if (DEBUG_TRACING) {
636                 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
637             }
638         }
639     }
640 
641     /**
642      * See {@link AppsFilterSnapshot#canQueryPackage(AndroidPackage, String)}
643      */
644     @Override
canQueryPackage(@onNull AndroidPackage querying, String potentialTarget)645     public boolean canQueryPackage(@NonNull AndroidPackage querying, String potentialTarget) {
646         int appId = UserHandle.getAppId(querying.getUid());
647         if (appId < Process.FIRST_APPLICATION_UID) {
648             return true;
649         }
650 
651         // Check if FILTER_APPLICATION_QUERY is enabled on the given package.
652         if (!mFeatureConfig.packageIsEnabled(querying)) {
653             return true;
654         }
655 
656         if (requestsQueryAllPackages(querying)) {
657             return true;
658         }
659 
660         return !querying.getQueriesPackages().isEmpty()
661                 && querying.getQueriesPackages().contains(potentialTarget);
662     }
663 
log(Object callingSetting, PackageStateInternal targetPkgSetting, String description)664     private static void log(Object callingSetting, PackageStateInternal targetPkgSetting,
665             String description) {
666         Slog.i(TAG,
667                 "interaction: " + (callingSetting == null ? "system" : callingSetting) + " -> "
668                         + targetPkgSetting + " " + description);
669     }
670 
getSharedUserPackages(int sharedUserAppId, Collection<SharedUserSetting> sharedUserSettings)671     protected ArraySet<? extends PackageStateInternal> getSharedUserPackages(int sharedUserAppId,
672             Collection<SharedUserSetting> sharedUserSettings) {
673         for (SharedUserSetting setting : sharedUserSettings) {
674             if (setting.mAppId != sharedUserAppId) {
675                 continue;
676             }
677             return setting.getPackageStates();
678         }
679         return new ArraySet<>();
680     }
681 
682     /**
683      * See {@link AppsFilterSnapshot#dumpQueries(PrintWriter, Integer, DumpState, int[],
684      * QuadFunction)}
685      */
686     @Override
dumpQueries( PrintWriter pw, @Nullable Integer filteringAppId, DumpState dumpState, int[] users, QuadFunction<Integer, Integer, Integer, Boolean, String[]> getPackagesForUid)687     public void dumpQueries(
688             PrintWriter pw, @Nullable Integer filteringAppId, DumpState dumpState, int[] users,
689             QuadFunction<Integer, Integer, Integer, Boolean, String[]> getPackagesForUid) {
690         final SparseArray<String> cache = new SparseArray<>();
691         ToString<Integer> expandPackages = input -> {
692             String cachedValue = cache.get(input);
693             if (cachedValue == null) {
694                 final int callingUid = Binder.getCallingUid();
695                 final int appId = UserHandle.getAppId(input);
696                 String[] packagesForUid = null;
697                 for (int i = 0, size = users.length; packagesForUid == null && i < size; i++) {
698                     packagesForUid = getPackagesForUid.apply(callingUid, users[i], appId,
699                             false /*isCallerInstantApp*/);
700                 }
701                 if (packagesForUid == null) {
702                     cachedValue = "[app id " + input + " not installed]";
703                 } else {
704                     cachedValue = packagesForUid.length == 1 ? packagesForUid[0]
705                             : "[" + TextUtils.join(",", packagesForUid) + "]";
706                 }
707                 cache.put(input, cachedValue);
708             }
709             return cachedValue;
710         };
711         pw.println();
712         pw.println("Queries:");
713         dumpState.onTitlePrinted();
714         if (!mFeatureConfig.isGloballyEnabled()) {
715             pw.println("  DISABLED");
716             if (!DEBUG_LOGGING) {
717                 return;
718             }
719         }
720         pw.println("  system apps queryable: " + mSystemAppsQueryable);
721         dumpForceQueryable(pw, filteringAppId, expandPackages);
722         dumpQueriesViaPackage(pw, filteringAppId, expandPackages);
723         dumpQueriesViaComponent(pw, filteringAppId, expandPackages);
724         dumpQueriesViaImplicitlyQueryable(pw, filteringAppId, users, expandPackages);
725         dumpQueriesViaUsesLibrary(pw, filteringAppId, expandPackages);
726     }
727 
dumpForceQueryable(PrintWriter pw, @Nullable Integer filteringAppId, ToString<Integer> expandPackages)728     protected void dumpForceQueryable(PrintWriter pw, @Nullable Integer filteringAppId,
729             ToString<Integer> expandPackages) {
730         pw.println("  queries via forceQueryable:");
731         dumpPackageSet(pw, filteringAppId, mForceQueryable.untrackedStorage(),
732                 "forceQueryable", "  ", expandPackages);
733     }
734 
dumpQueriesViaPackage(PrintWriter pw, @Nullable Integer filteringAppId, ToString<Integer> expandPackages)735     protected void dumpQueriesViaPackage(PrintWriter pw, @Nullable Integer filteringAppId,
736             ToString<Integer> expandPackages) {
737         pw.println("  queries via package name:");
738         dumpQueriesMap(pw, filteringAppId, mQueriesViaPackage, "    ", expandPackages);
739     }
740 
dumpQueriesViaComponent(PrintWriter pw, @Nullable Integer filteringAppId, ToString<Integer> expandPackages)741     protected void dumpQueriesViaComponent(PrintWriter pw, @Nullable Integer filteringAppId,
742             ToString<Integer> expandPackages) {
743         pw.println("  queries via component:");
744         dumpQueriesMap(pw, filteringAppId, mQueriesViaComponent, "    ", expandPackages);
745     }
746 
dumpQueriesViaImplicitlyQueryable(PrintWriter pw, @Nullable Integer filteringAppId, int[] users, ToString<Integer> expandPackages)747     protected void dumpQueriesViaImplicitlyQueryable(PrintWriter pw,
748             @Nullable Integer filteringAppId, int[] users, ToString<Integer> expandPackages) {
749         pw.println("  queryable via interaction:");
750         for (int user : users) {
751             pw.append("    User ").append(Integer.toString(user)).println(":");
752             dumpQueriesMap(pw,
753                     filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId),
754                     mImplicitlyQueryable, "      ", expandPackages);
755             dumpQueriesMap(pw,
756                     filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId),
757                     mRetainedImplicitlyQueryable, "      ", expandPackages);
758         }
759     }
760 
dumpQueriesViaUsesLibrary(PrintWriter pw, @Nullable Integer filteringAppId, ToString<Integer> expandPackages)761     protected void dumpQueriesViaUsesLibrary(PrintWriter pw, @Nullable Integer filteringAppId,
762             ToString<Integer> expandPackages) {
763         pw.println("  queryable via uses-library:");
764         dumpQueriesMap(pw, filteringAppId, mQueryableViaUsesLibrary, "    ",
765                 expandPackages);
766     }
767 
dumpQueriesMap(PrintWriter pw, @Nullable Integer filteringId, WatchedSparseSetArray<Integer> queriesMap, String spacing, @Nullable ToString<Integer> toString)768     private static void dumpQueriesMap(PrintWriter pw, @Nullable Integer filteringId,
769             WatchedSparseSetArray<Integer> queriesMap, String spacing,
770             @Nullable ToString<Integer> toString) {
771         for (int i = 0; i < queriesMap.size(); i++) {
772             Integer callingId = queriesMap.keyAt(i);
773             if (Objects.equals(callingId, filteringId)) {
774                 // don't filter target package names if the calling is filteringId
775                 dumpPackageSet(
776                         pw, null /*filteringId*/, queriesMap.get(callingId),
777                         toString == null
778                                 ? callingId.toString()
779                                 : toString.toString(callingId),
780                         spacing, toString);
781             } else {
782                 dumpPackageSet(
783                         pw, filteringId, queriesMap.get(callingId),
784                         toString == null
785                                 ? callingId.toString()
786                                 : toString.toString(callingId),
787                         spacing, toString);
788             }
789         }
790     }
791 
792     protected interface ToString<T> {
toString(T input)793         String toString(T input);
794     }
795 
dumpPackageSet(PrintWriter pw, @Nullable T filteringId, ArraySet<T> targetPkgSet, String subTitle, String spacing, @Nullable ToString<T> toString)796     private static <T> void dumpPackageSet(PrintWriter pw, @Nullable T filteringId,
797             ArraySet<T> targetPkgSet, String subTitle, String spacing,
798             @Nullable ToString<T> toString) {
799         if (targetPkgSet != null && targetPkgSet.size() > 0
800                 && (filteringId == null || targetPkgSet.contains(filteringId))) {
801             pw.append(spacing).append(subTitle).println(":");
802             for (T item : targetPkgSet) {
803                 if (filteringId == null || Objects.equals(filteringId, item)) {
804                     pw.append(spacing).append("  ")
805                             .println(toString == null ? item : toString.toString(item));
806                 }
807             }
808         }
809     }
810 }
811