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