• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.content.pm.PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
20 import static android.content.pm.PackageManagerInternal.PACKAGE_SETUP_WIZARD;
21 
22 import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
23 import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
24 
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.content.ComponentName;
28 import android.content.Intent;
29 import android.content.IntentFilter;
30 import android.content.pm.ActivityInfo;
31 import android.content.pm.ApplicationInfo;
32 import android.content.pm.AuxiliaryResolveInfo;
33 import android.content.pm.InstantAppResolveInfo;
34 import android.content.pm.PackageManager;
35 import android.content.pm.PackageManagerInternal;
36 import android.content.pm.PackageUserState;
37 import android.content.pm.ProviderInfo;
38 import android.content.pm.ResolveInfo;
39 import android.content.pm.ServiceInfo;
40 import android.content.pm.parsing.component.ParsedActivity;
41 import android.content.pm.parsing.component.ParsedComponent;
42 import android.content.pm.parsing.component.ParsedIntentInfo;
43 import android.content.pm.parsing.component.ParsedMainComponent;
44 import android.content.pm.parsing.component.ParsedProvider;
45 import android.content.pm.parsing.component.ParsedService;
46 import android.os.UserHandle;
47 import android.util.ArrayMap;
48 import android.util.ArraySet;
49 import android.util.DebugUtils;
50 import android.util.Log;
51 import android.util.LogPrinter;
52 import android.util.Pair;
53 import android.util.Slog;
54 
55 import com.android.internal.annotations.GuardedBy;
56 import com.android.internal.annotations.VisibleForTesting;
57 import com.android.internal.util.ArrayUtils;
58 import com.android.server.IntentResolver;
59 import com.android.server.pm.parsing.PackageInfoUtils;
60 import com.android.server.pm.parsing.PackageInfoUtils.CachedApplicationInfoGenerator;
61 import com.android.server.pm.parsing.pkg.AndroidPackage;
62 import com.android.server.utils.Snappable;
63 import com.android.server.utils.SnapshotCache;
64 import com.android.server.utils.WatchableImpl;
65 
66 import java.io.PrintWriter;
67 import java.util.ArrayList;
68 import java.util.Collections;
69 import java.util.Comparator;
70 import java.util.Iterator;
71 import java.util.List;
72 import java.util.Map;
73 import java.util.Objects;
74 import java.util.Set;
75 import java.util.function.Function;
76 
77 /** Resolves all Android component types [activities, services, providers and receivers]. */
78 public class ComponentResolver
79         extends WatchableImpl
80         implements Snappable {
81     private static final boolean DEBUG = false;
82     private static final String TAG = "PackageManager";
83     private static final boolean DEBUG_FILTERS = false;
84     private static final boolean DEBUG_SHOW_INFO = false;
85 
86     // Convenience function to report that this object has changed.
onChanged()87     private void onChanged() {
88         dispatchChange(this);
89     }
90 
91     /**
92      * The set of all protected actions [i.e. those actions for which a high priority
93      * intent filter is disallowed].
94      */
95     private static final Set<String> PROTECTED_ACTIONS = new ArraySet<>();
96     static {
97         PROTECTED_ACTIONS.add(Intent.ACTION_SEND);
98         PROTECTED_ACTIONS.add(Intent.ACTION_SENDTO);
99         PROTECTED_ACTIONS.add(Intent.ACTION_SEND_MULTIPLE);
100         PROTECTED_ACTIONS.add(Intent.ACTION_VIEW);
101     }
102 
103     static final Comparator<ResolveInfo> RESOLVE_PRIORITY_SORTER = (r1, r2) -> {
104         int v1 = r1.priority;
105         int v2 = r2.priority;
106         //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
107         if (v1 != v2) {
108             return (v1 > v2) ? -1 : 1;
109         }
110         v1 = r1.preferredOrder;
111         v2 = r2.preferredOrder;
112         if (v1 != v2) {
113             return (v1 > v2) ? -1 : 1;
114         }
115         if (r1.isDefault != r2.isDefault) {
116             return r1.isDefault ? -1 : 1;
117         }
118         v1 = r1.match;
119         v2 = r2.match;
120         //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
121         if (v1 != v2) {
122             return (v1 > v2) ? -1 : 1;
123         }
124         if (r1.system != r2.system) {
125             return r1.system ? -1 : 1;
126         }
127         if (r1.activityInfo != null) {
128             return r1.activityInfo.packageName.compareTo(r2.activityInfo.packageName);
129         }
130         if (r1.serviceInfo != null) {
131             return r1.serviceInfo.packageName.compareTo(r2.serviceInfo.packageName);
132         }
133         if (r1.providerInfo != null) {
134             return r1.providerInfo.packageName.compareTo(r2.providerInfo.packageName);
135         }
136         return 0;
137     };
138 
139     private static UserManagerService sUserManager;
140     private static PackageManagerInternal sPackageManagerInternal;
141 
142     /**
143      * Locking within package manager is going to get worse before it gets better. Currently,
144      * we need to share the {@link PackageManagerService} lock to prevent deadlocks. This occurs
145      * because in order to safely query the resolvers, we need to obtain this lock. However,
146      * during resolution, we call into the {@link PackageManagerService}. This is _not_ to
147      * operate on data controlled by the service proper, but, to check the state of package
148      * settings [contained in a {@link Settings} object]. However, the {@link Settings} object
149      * happens to be protected by the main {@link PackageManagerService} lock.
150      * <p>
151      * There are a couple potential solutions.
152      * <ol>
153      * <li>Split all of our locks into reader/writer locks. This would allow multiple,
154      * simultaneous read operations and means we don't have to be as cautious about lock
155      * layering. Only when we want to perform a write operation will we ever be in a
156      * position to deadlock the system.</li>
157      * <li>Use the same lock across all classes within the {@code com.android.server.pm}
158      * package. By unifying the lock object, we remove any potential lock layering issues
159      * within the package manager. However, we already have a sense that this lock is
160      * heavily contended and merely adding more dependencies on it will have further
161      * impact.</li>
162      * <li>Implement proper lock ordering within the package manager. By defining the
163      * relative layer of the component [eg. {@link PackageManagerService} is at the top.
164      * Somewhere in the middle would be {@link ComponentResolver}. At the very bottom
165      * would be {@link Settings}.] The ordering would allow higher layers to hold their
166      * lock while calling down. Lower layers must relinquish their lock before calling up.
167      * Since {@link Settings} would live at the lowest layer, the {@link ComponentResolver}
168      * would be able to hold its lock while checking the package setting state.</li>
169      * </ol>
170      */
171     private final PackageManagerTracedLock mLock;
172 
173     /** All available activities, for your resolving pleasure. */
174     @GuardedBy("mLock")
175     private final ActivityIntentResolver mActivities;
176 
177     /** All available providers, for your resolving pleasure. */
178     @GuardedBy("mLock")
179     private final ProviderIntentResolver mProviders;
180 
181     /** All available receivers, for your resolving pleasure. */
182     @GuardedBy("mLock")
183     private final ReceiverIntentResolver mReceivers;
184 
185     /** All available services, for your resolving pleasure. */
186     @GuardedBy("mLock")
187     private final ServiceIntentResolver mServices;
188 
189     /** Mapping from provider authority [first directory in content URI codePath) to provider. */
190     @GuardedBy("mLock")
191     private final ArrayMap<String, ParsedProvider> mProvidersByAuthority;
192 
193     /** Whether or not processing protected filters should be deferred. */
194     private boolean mDeferProtectedFilters = true;
195 
196     /**
197      * Tracks high priority intent filters for protected actions. During boot, certain
198      * filter actions are protected and should never be allowed to have a high priority
199      * intent filter for them. However, there is one, and only one exception -- the
200      * setup wizard. It must be able to define a high priority intent filter for these
201      * actions to ensure there are no escapes from the wizard. We need to delay processing
202      * of these during boot as we need to inspect at all of the intent filters on the
203      * /system partition in order to know which component is the setup wizard. This can
204      * only ever be non-empty if {@link #mDeferProtectedFilters} is {@code true}.
205      *
206      * This is a pair of component package name to actual filter, because we don't store the
207      * name inside the filter. It's technically independent of the component it's contained in.
208      */
209     private List<Pair<ParsedMainComponent, ParsedIntentInfo>> mProtectedFilters;
210 
ComponentResolver(UserManagerService userManager, PackageManagerInternal packageManagerInternal, PackageManagerTracedLock lock)211     ComponentResolver(UserManagerService userManager,
212             PackageManagerInternal packageManagerInternal,
213             PackageManagerTracedLock lock) {
214         sPackageManagerInternal = packageManagerInternal;
215         sUserManager = userManager;
216         mLock = lock;
217 
218         mActivities = new ActivityIntentResolver();
219         mProviders = new ProviderIntentResolver();
220         mReceivers = new ReceiverIntentResolver();
221         mServices = new ServiceIntentResolver();
222         mProvidersByAuthority = new ArrayMap<>();
223         mDeferProtectedFilters = true;
224 
225         mSnapshot = new SnapshotCache<ComponentResolver>(this, this) {
226                 @Override
227                 public ComponentResolver createSnapshot() {
228                     return new ComponentResolver(mSource);
229                 }};
230     }
231 
232     // Copy constructor used in creating snapshots.
ComponentResolver(ComponentResolver orig)233     private ComponentResolver(ComponentResolver orig) {
234         // Do not set the static variables that are set in the default constructor.   Do
235         // create a new object for the lock.  The snapshot is read-only, so a lock is not
236         // strictly required.  However, the current code is simpler if the lock exists,
237         // but does not contend with any outside class.
238         // TODO: make the snapshot lock-free
239         mLock = new PackageManagerTracedLock();
240 
241         mActivities = new ActivityIntentResolver(orig.mActivities);
242         mProviders = new ProviderIntentResolver(orig.mProviders);
243         mReceivers = new ReceiverIntentResolver(orig.mReceivers);
244         mServices = new ServiceIntentResolver(orig.mServices);
245         mProvidersByAuthority = new ArrayMap<>(orig.mProvidersByAuthority);
246         mDeferProtectedFilters = orig.mDeferProtectedFilters;
247         mProtectedFilters = (mProtectedFilters == null)
248                             ? null
249                             : new ArrayList<>(orig.mProtectedFilters);
250 
251         mSnapshot = null;
252     }
253 
254     final SnapshotCache<ComponentResolver> mSnapshot;
255 
256     /**
257      * Create a snapshot.
258      */
snapshot()259     public ComponentResolver snapshot() {
260         return mSnapshot.snapshot();
261     }
262 
263 
264     /** Returns the given activity */
265     @Nullable
266     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
getActivity(@onNull ComponentName component)267     public ParsedActivity getActivity(@NonNull ComponentName component) {
268         synchronized (mLock) {
269             return mActivities.mActivities.get(component);
270         }
271     }
272 
273     /** Returns the given provider */
274     @Nullable
getProvider(@onNull ComponentName component)275     ParsedProvider getProvider(@NonNull ComponentName component) {
276         synchronized (mLock) {
277             return mProviders.mProviders.get(component);
278         }
279     }
280 
281     /** Returns the given receiver */
282     @Nullable
getReceiver(@onNull ComponentName component)283     ParsedActivity getReceiver(@NonNull ComponentName component) {
284         synchronized (mLock) {
285             return mReceivers.mActivities.get(component);
286         }
287     }
288 
289     /** Returns the given service */
290     @Nullable
getService(@onNull ComponentName component)291     ParsedService getService(@NonNull ComponentName component) {
292         synchronized (mLock) {
293             return mServices.mServices.get(component);
294         }
295     }
296 
297     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
componentExists(@onNull ComponentName componentName)298     public boolean componentExists(@NonNull ComponentName componentName) {
299         synchronized (mLock) {
300             ParsedMainComponent component = mActivities.mActivities.get(componentName);
301             if (component != null) {
302                 return true;
303             }
304             component = mReceivers.mActivities.get(componentName);
305             if (component != null) {
306                 return true;
307             }
308             component = mServices.mServices.get(componentName);
309             if (component != null) {
310                 return true;
311             }
312             return mProviders.mProviders.get(componentName) != null;
313         }
314     }
315 
316     @Nullable
queryActivities(Intent intent, String resolvedType, int flags, int userId)317     List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags,
318             int userId) {
319         synchronized (mLock) {
320             return mActivities.queryIntent(intent, resolvedType, flags, userId);
321         }
322     }
323 
324     @Nullable
queryActivities(Intent intent, String resolvedType, int flags, List<ParsedActivity> activities, int userId)325     List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags,
326             List<ParsedActivity> activities, int userId) {
327         synchronized (mLock) {
328             return mActivities.queryIntentForPackage(
329                     intent, resolvedType, flags, activities, userId);
330         }
331     }
332 
333     @Nullable
queryProviders(Intent intent, String resolvedType, int flags, int userId)334     List<ResolveInfo> queryProviders(Intent intent, String resolvedType, int flags, int userId) {
335         synchronized (mLock) {
336             return mProviders.queryIntent(intent, resolvedType, flags, userId);
337         }
338     }
339 
340     @Nullable
queryProviders(Intent intent, String resolvedType, int flags, List<ParsedProvider> providers, int userId)341     List<ResolveInfo> queryProviders(Intent intent, String resolvedType, int flags,
342             List<ParsedProvider> providers, int userId) {
343         synchronized (mLock) {
344             return mProviders.queryIntentForPackage(intent, resolvedType, flags, providers, userId);
345         }
346     }
347 
348     @Nullable
queryProviders(String processName, String metaDataKey, int uid, int flags, int userId)349     List<ProviderInfo> queryProviders(String processName, String metaDataKey, int uid, int flags,
350             int userId) {
351         if (!sUserManager.exists(userId)) {
352             return null;
353         }
354         List<ProviderInfo> providerList = null;
355         CachedApplicationInfoGenerator appInfoGenerator = null;
356         synchronized (mLock) {
357             for (int i = mProviders.mProviders.size() - 1; i >= 0; --i) {
358                 final ParsedProvider p = mProviders.mProviders.valueAt(i);
359                 if (p.getAuthority() == null) {
360                     continue;
361                 }
362 
363                 final PackageSetting ps =
364                         (PackageSetting) sPackageManagerInternal.getPackageSetting(
365                                 p.getPackageName());
366                 if (ps == null) {
367                     continue;
368                 }
369 
370                 AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName());
371                 if (pkg == null) {
372                     continue;
373                 }
374 
375                 if (processName != null && (!p.getProcessName().equals(processName)
376                         || !UserHandle.isSameApp(pkg.getUid(), uid))) {
377                     continue;
378                 }
379                 // See PM.queryContentProviders()'s javadoc for why we have the metaData parameter.
380                 if (metaDataKey != null
381                         && (p.getMetaData() == null || !p.getMetaData().containsKey(metaDataKey))) {
382                     continue;
383                 }
384                 if (appInfoGenerator == null) {
385                     appInfoGenerator = new CachedApplicationInfoGenerator();
386                 }
387                 final PackageUserState state = ps.readUserState(userId);
388                 final ApplicationInfo appInfo =
389                         appInfoGenerator.generate(pkg, flags, state, userId, ps);
390                 if (appInfo == null) {
391                     continue;
392                 }
393 
394                 final ProviderInfo info = PackageInfoUtils.generateProviderInfo(
395                         pkg, p, flags, state, appInfo, userId, ps);
396                 if (info == null) {
397                     continue;
398                 }
399                 if (providerList == null) {
400                     providerList = new ArrayList<>(i + 1);
401                 }
402                 providerList.add(info);
403             }
404         }
405         return providerList;
406     }
407 
408     @Nullable
queryProvider(String authority, int flags, int userId)409     ProviderInfo queryProvider(String authority, int flags, int userId) {
410         synchronized (mLock) {
411             final ParsedProvider p = mProvidersByAuthority.get(authority);
412             if (p == null) {
413                 return null;
414             }
415             final PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting(
416                     p.getPackageName());
417             if (ps == null) {
418                 return null;
419             }
420             final AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName());
421             if (pkg == null) {
422                 return null;
423             }
424             final PackageUserState state = ps.readUserState(userId);
425             ApplicationInfo appInfo = PackageInfoUtils.generateApplicationInfo(
426                     pkg, flags, state, userId, ps);
427             if (appInfo == null) {
428                 return null;
429             }
430             return PackageInfoUtils.generateProviderInfo(pkg, p, flags, state, appInfo, userId, ps);
431         }
432     }
433 
querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo, boolean safeMode, int userId)434     void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo, boolean safeMode,
435             int userId) {
436         synchronized (mLock) {
437             CachedApplicationInfoGenerator appInfoGenerator = null;
438             for (int i = mProvidersByAuthority.size() - 1; i >= 0; --i) {
439                 final ParsedProvider p = mProvidersByAuthority.valueAt(i);
440                 if (!p.isSyncable()) {
441                     continue;
442                 }
443 
444                 final PackageSetting ps =
445                         (PackageSetting) sPackageManagerInternal.getPackageSetting(
446                                 p.getPackageName());
447                 if (ps == null) {
448                     continue;
449                 }
450 
451                 final AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName());
452                 if (pkg == null) {
453                     continue;
454                 }
455 
456                 if (safeMode && !pkg.isSystem()) {
457                     continue;
458                 }
459                 if (appInfoGenerator == null) {
460                     appInfoGenerator = new CachedApplicationInfoGenerator();
461                 }
462                 final PackageUserState state = ps.readUserState(userId);
463                 final ApplicationInfo appInfo =
464                         appInfoGenerator.generate(pkg, 0, state, userId, ps);
465                 if (appInfo == null) {
466                     continue;
467                 }
468 
469                 final ProviderInfo info = PackageInfoUtils.generateProviderInfo(
470                         pkg, p, 0, state, appInfo, userId, ps);
471                 if (info == null) {
472                     continue;
473                 }
474                 outNames.add(mProvidersByAuthority.keyAt(i));
475                 outInfo.add(info);
476             }
477         }
478     }
479 
480     @Nullable
queryReceivers(Intent intent, String resolvedType, int flags, int userId)481     List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags, int userId) {
482         synchronized (mLock) {
483             return mReceivers.queryIntent(intent, resolvedType, flags, userId);
484         }
485     }
486 
487     @Nullable
queryReceivers(Intent intent, String resolvedType, int flags, List<ParsedActivity> receivers, int userId)488     List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags,
489             List<ParsedActivity> receivers, int userId) {
490         synchronized (mLock) {
491             return mReceivers.queryIntentForPackage(intent, resolvedType, flags, receivers, userId);
492         }
493     }
494 
495     @Nullable
queryServices(Intent intent, String resolvedType, int flags, int userId)496     List<ResolveInfo> queryServices(Intent intent, String resolvedType, int flags, int userId) {
497         synchronized (mLock) {
498             return mServices.queryIntent(intent, resolvedType, flags, userId);
499         }
500     }
501 
502     @Nullable
queryServices(Intent intent, String resolvedType, int flags, List<ParsedService> services, int userId)503     List<ResolveInfo> queryServices(Intent intent, String resolvedType, int flags,
504             List<ParsedService> services, int userId) {
505         synchronized (mLock) {
506             return mServices.queryIntentForPackage(intent, resolvedType, flags, services, userId);
507         }
508     }
509 
510     /** Returns {@code true} if the given activity is defined by some package */
isActivityDefined(ComponentName component)511     boolean isActivityDefined(ComponentName component) {
512         synchronized (mLock) {
513             return mActivities.mActivities.get(component) != null;
514         }
515     }
516 
517     /** Asserts none of the providers defined in the given package haven't already been defined. */
assertProvidersNotDefined(AndroidPackage pkg)518     void assertProvidersNotDefined(AndroidPackage pkg) throws PackageManagerException {
519         synchronized (mLock) {
520             assertProvidersNotDefinedLocked(pkg);
521         }
522     }
523 
524     /** Add all components defined in the given package to the internal structures. */
addAllComponents(AndroidPackage pkg, boolean chatty)525     void addAllComponents(AndroidPackage pkg, boolean chatty) {
526         final ArrayList<Pair<ParsedActivity, ParsedIntentInfo>> newIntents = new ArrayList<>();
527         synchronized (mLock) {
528             addActivitiesLocked(pkg, newIntents, chatty);
529             addReceiversLocked(pkg, chatty);
530             addProvidersLocked(pkg, chatty);
531             addServicesLocked(pkg, chatty);
532             onChanged();
533         }
534         // expect single setupwizard package
535         final String setupWizardPackage = ArrayUtils.firstOrNull(
536                 sPackageManagerInternal.getKnownPackageNames(
537                         PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM));
538 
539         for (int i = newIntents.size() - 1; i >= 0; --i) {
540             final Pair<ParsedActivity, ParsedIntentInfo> pair = newIntents.get(i);
541             final PackageSetting disabledPkgSetting = (PackageSetting) sPackageManagerInternal
542                     .getDisabledSystemPackage(pair.first.getPackageName());
543             final AndroidPackage disabledPkg =
544                     disabledPkgSetting == null ? null : disabledPkgSetting.pkg;
545             final List<ParsedActivity> systemActivities =
546                     disabledPkg != null ? disabledPkg.getActivities() : null;
547             adjustPriority(systemActivities, pair.first, pair.second, setupWizardPackage);
548             onChanged();
549         }
550     }
551 
552     /** Removes all components defined in the given package from the internal structures. */
removeAllComponents(AndroidPackage pkg, boolean chatty)553     void removeAllComponents(AndroidPackage pkg, boolean chatty) {
554         synchronized (mLock) {
555             removeAllComponentsLocked(pkg, chatty);
556             onChanged();
557         }
558     }
559 
560     /**
561      * Reprocess any protected filters that have been deferred. At this point, we've scanned
562      * all of the filters defined on the /system partition and know the special components.
563      */
fixProtectedFilterPriorities()564     void fixProtectedFilterPriorities() {
565         synchronized (mLock) {
566             if (!mDeferProtectedFilters) {
567                 return;
568             }
569             mDeferProtectedFilters = false;
570 
571             if (mProtectedFilters == null || mProtectedFilters.size() == 0) {
572                 return;
573             }
574             final List<Pair<ParsedMainComponent, ParsedIntentInfo>> protectedFilters =
575                     mProtectedFilters;
576             mProtectedFilters = null;
577 
578             // expect single setupwizard package
579             final String setupWizardPackage = ArrayUtils.firstOrNull(
580                 sPackageManagerInternal.getKnownPackageNames(
581                     PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM));
582 
583             if (DEBUG_FILTERS && setupWizardPackage == null) {
584                 Slog.i(TAG, "No setup wizard;"
585                         + " All protected intents capped to priority 0");
586             }
587             for (int i = protectedFilters.size() - 1; i >= 0; --i) {
588                 final Pair<ParsedMainComponent, ParsedIntentInfo> pair = protectedFilters.get(i);
589                 ParsedMainComponent component = pair.first;
590                 ParsedIntentInfo filter = pair.second;
591                 String packageName = component.getPackageName();
592                 String className = component.getClassName();
593                 if (packageName.equals(setupWizardPackage)) {
594                     if (DEBUG_FILTERS) {
595                         Slog.i(TAG, "Found setup wizard;"
596                                 + " allow priority " + filter.getPriority() + ";"
597                                 + " package: " + packageName
598                                 + " activity: " + className
599                                 + " priority: " + filter.getPriority());
600                     }
601                     // skip setup wizard; allow it to keep the high priority filter
602                     continue;
603                 }
604                 if (DEBUG_FILTERS) {
605                     Slog.i(TAG, "Protected action; cap priority to 0;"
606                             + " package: " + packageName
607                             + " activity: " + className
608                             + " origPrio: " + filter.getPriority());
609                 }
610                 filter.setPriority(0);
611             }
612             onChanged();
613         }
614     }
615 
dumpActivityResolvers(PrintWriter pw, DumpState dumpState, String packageName)616     void dumpActivityResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
617         if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
618                 : "Activity Resolver Table:", "  ", packageName,
619                 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
620             dumpState.setTitlePrinted(true);
621         }
622     }
623 
dumpProviderResolvers(PrintWriter pw, DumpState dumpState, String packageName)624     void dumpProviderResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
625         if (mProviders.dump(pw, dumpState.getTitlePrinted() ? "\nProvider Resolver Table:"
626                 : "Provider Resolver Table:", "  ", packageName,
627                 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
628             dumpState.setTitlePrinted(true);
629         }
630     }
631 
dumpReceiverResolvers(PrintWriter pw, DumpState dumpState, String packageName)632     void dumpReceiverResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
633         if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:"
634                 : "Receiver Resolver Table:", "  ", packageName,
635                 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
636             dumpState.setTitlePrinted(true);
637         }
638     }
639 
dumpServiceResolvers(PrintWriter pw, DumpState dumpState, String packageName)640     void dumpServiceResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
641         if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:"
642                 : "Service Resolver Table:", "  ", packageName,
643                 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
644             dumpState.setTitlePrinted(true);
645         }
646     }
647 
dumpContentProviders(PrintWriter pw, DumpState dumpState, String packageName)648     void dumpContentProviders(PrintWriter pw, DumpState dumpState, String packageName) {
649         boolean printedSomething = false;
650         for (ParsedProvider p : mProviders.mProviders.values()) {
651             if (packageName != null && !packageName.equals(p.getPackageName())) {
652                 continue;
653             }
654             if (!printedSomething) {
655                 if (dumpState.onTitlePrinted()) {
656                     pw.println();
657                 }
658                 pw.println("Registered ContentProviders:");
659                 printedSomething = true;
660             }
661             pw.print("  ");
662             ComponentName.printShortString(pw, p.getPackageName(), p.getName());
663             pw.println(":");
664             pw.print("    ");
665             pw.println(p.toString());
666         }
667         printedSomething = false;
668         for (Map.Entry<String, ParsedProvider> entry :
669                 mProvidersByAuthority.entrySet()) {
670             ParsedProvider p = entry.getValue();
671             if (packageName != null && !packageName.equals(p.getPackageName())) {
672                 continue;
673             }
674             if (!printedSomething) {
675                 if (dumpState.onTitlePrinted()) {
676                     pw.println();
677                 }
678                 pw.println("ContentProvider Authorities:");
679                 printedSomething = true;
680             }
681             pw.print("  ["); pw.print(entry.getKey()); pw.println("]:");
682             pw.print("    "); pw.println(p.toString());
683 
684             AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName());
685 
686             if (pkg != null) {
687                 pw.print("      applicationInfo="); pw.println(pkg.toAppInfoWithoutState());
688             }
689         }
690     }
691 
dumpServicePermissions(PrintWriter pw, DumpState dumpState)692     void dumpServicePermissions(PrintWriter pw, DumpState dumpState) {
693         if (dumpState.onTitlePrinted()) pw.println();
694         pw.println("Service permissions:");
695 
696         final Iterator<Pair<ParsedService, ParsedIntentInfo>> filterIterator =
697                 mServices.filterIterator();
698         while (filterIterator.hasNext()) {
699             final Pair<ParsedService, ParsedIntentInfo> pair = filterIterator.next();
700             ParsedService service = pair.first;
701 
702             final String permission = service.getPermission();
703             if (permission != null) {
704                 pw.print("    ");
705                 pw.print(service.getComponentName().flattenToShortString());
706                 pw.print(": ");
707                 pw.println(permission);
708             }
709         }
710     }
711 
712     @GuardedBy("mLock")
addActivitiesLocked(AndroidPackage pkg, List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents, boolean chatty)713     private void addActivitiesLocked(AndroidPackage pkg,
714             List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents, boolean chatty) {
715         final int activitiesSize = ArrayUtils.size(pkg.getActivities());
716         StringBuilder r = null;
717         for (int i = 0; i < activitiesSize; i++) {
718             ParsedActivity a = pkg.getActivities().get(i);
719             mActivities.addActivity(a, "activity", newIntents);
720             if (DEBUG_PACKAGE_SCANNING && chatty) {
721                 if (r == null) {
722                     r = new StringBuilder(256);
723                 } else {
724                     r.append(' ');
725                 }
726                 r.append(a.getName());
727             }
728         }
729         if (DEBUG_PACKAGE_SCANNING && chatty) {
730             Log.d(TAG, "  Activities: " + (r == null ? "<NONE>" : r));
731         }
732     }
733 
734     @GuardedBy("mLock")
addProvidersLocked(AndroidPackage pkg, boolean chatty)735     private void addProvidersLocked(AndroidPackage pkg, boolean chatty) {
736         final int providersSize = ArrayUtils.size(pkg.getProviders());
737         StringBuilder r = null;
738         for (int i = 0; i < providersSize; i++) {
739             ParsedProvider p = pkg.getProviders().get(i);
740             mProviders.addProvider(p);
741             if (p.getAuthority() != null) {
742                 String[] names = p.getAuthority().split(";");
743 
744                 // TODO(b/135203078): Remove this mutation
745                 p.setAuthority(null);
746                 for (int j = 0; j < names.length; j++) {
747                     if (j == 1 && p.isSyncable()) {
748                         // We only want the first authority for a provider to possibly be
749                         // syncable, so if we already added this provider using a different
750                         // authority clear the syncable flag. We copy the provider before
751                         // changing it because the mProviders object contains a reference
752                         // to a provider that we don't want to change.
753                         // Only do this for the second authority since the resulting provider
754                         // object can be the same for all future authorities for this provider.
755                         p = new ParsedProvider(p);
756                         p.setSyncable(false);
757                     }
758                     if (!mProvidersByAuthority.containsKey(names[j])) {
759                         mProvidersByAuthority.put(names[j], p);
760                         if (p.getAuthority() == null) {
761                             p.setAuthority(names[j]);
762                         } else {
763                             p.setAuthority(p.getAuthority() + ";" + names[j]);
764                         }
765                         if (DEBUG_PACKAGE_SCANNING && chatty) {
766                             Log.d(TAG, "Registered content provider: " + names[j]
767                                     + ", className = " + p.getName()
768                                     + ", isSyncable = " + p.isSyncable());
769                         }
770                     } else {
771                         final ParsedProvider other =
772                                 mProvidersByAuthority.get(names[j]);
773                         final ComponentName component =
774                                 (other != null && other.getComponentName() != null)
775                                         ? other.getComponentName() : null;
776                         final String packageName =
777                                 component != null ? component.getPackageName() : "?";
778                         Slog.w(TAG, "Skipping provider name " + names[j]
779                                 + " (in package " + pkg.getPackageName() + ")"
780                                 + ": name already used by " + packageName);
781                     }
782                 }
783             }
784             if (DEBUG_PACKAGE_SCANNING && chatty) {
785                 if (r == null) {
786                     r = new StringBuilder(256);
787                 } else {
788                     r.append(' ');
789                 }
790                 r.append(p.getName());
791             }
792         }
793         if (DEBUG_PACKAGE_SCANNING && chatty) {
794             Log.d(TAG, "  Providers: " + (r == null ? "<NONE>" : r));
795         }
796     }
797 
798     @GuardedBy("mLock")
addReceiversLocked(AndroidPackage pkg, boolean chatty)799     private void addReceiversLocked(AndroidPackage pkg, boolean chatty) {
800         final int receiversSize = ArrayUtils.size(pkg.getReceivers());
801         StringBuilder r = null;
802         for (int i = 0; i < receiversSize; i++) {
803             ParsedActivity a = pkg.getReceivers().get(i);
804             mReceivers.addActivity(a, "receiver", null);
805             if (DEBUG_PACKAGE_SCANNING && chatty) {
806                 if (r == null) {
807                     r = new StringBuilder(256);
808                 } else {
809                     r.append(' ');
810                 }
811                 r.append(a.getName());
812             }
813         }
814         if (DEBUG_PACKAGE_SCANNING && chatty) {
815             Log.d(TAG, "  Receivers: " + (r == null ? "<NONE>" : r));
816         }
817     }
818 
819     @GuardedBy("mLock")
addServicesLocked(AndroidPackage pkg, boolean chatty)820     private void addServicesLocked(AndroidPackage pkg, boolean chatty) {
821         final int servicesSize = ArrayUtils.size(pkg.getServices());
822         StringBuilder r = null;
823         for (int i = 0; i < servicesSize; i++) {
824             ParsedService s = pkg.getServices().get(i);
825             mServices.addService(s);
826             if (DEBUG_PACKAGE_SCANNING && chatty) {
827                 if (r == null) {
828                     r = new StringBuilder(256);
829                 } else {
830                     r.append(' ');
831                 }
832                 r.append(s.getName());
833             }
834         }
835         if (DEBUG_PACKAGE_SCANNING && chatty) {
836             Log.d(TAG, "  Services: " + (r == null ? "<NONE>" : r));
837         }
838     }
839 
840     /**
841      * <em>WARNING</em> for performance reasons, the passed in intentList WILL BE
842      * MODIFIED. Do not pass in a list that should not be changed.
843      */
getIntentListSubset(List<ParsedIntentInfo> intentList, Function<ParsedIntentInfo, Iterator<T>> generator, Iterator<T> searchIterator)844     private static <T> void getIntentListSubset(List<ParsedIntentInfo> intentList,
845             Function<ParsedIntentInfo, Iterator<T>> generator, Iterator<T> searchIterator) {
846         // loop through the set of actions; every one must be found in the intent filter
847         while (searchIterator.hasNext()) {
848             // we must have at least one filter in the list to consider a match
849             if (intentList.size() == 0) {
850                 break;
851             }
852 
853             final T searchAction = searchIterator.next();
854 
855             // loop through the set of intent filters
856             final Iterator<ParsedIntentInfo> intentIter = intentList.iterator();
857             while (intentIter.hasNext()) {
858                 final ParsedIntentInfo intentInfo = intentIter.next();
859                 boolean selectionFound = false;
860 
861                 // loop through the intent filter's selection criteria; at least one
862                 // of them must match the searched criteria
863                 final Iterator<T> intentSelectionIter = generator.apply(intentInfo);
864                 while (intentSelectionIter != null && intentSelectionIter.hasNext()) {
865                     final T intentSelection = intentSelectionIter.next();
866                     if (intentSelection != null && intentSelection.equals(searchAction)) {
867                         selectionFound = true;
868                         break;
869                     }
870                 }
871 
872                 // the selection criteria wasn't found in this filter's set; this filter
873                 // is not a potential match
874                 if (!selectionFound) {
875                     intentIter.remove();
876                 }
877             }
878         }
879     }
880 
isProtectedAction(ParsedIntentInfo filter)881     private static boolean isProtectedAction(ParsedIntentInfo filter) {
882         final Iterator<String> actionsIter = filter.actionsIterator();
883         while (actionsIter != null && actionsIter.hasNext()) {
884             final String filterAction = actionsIter.next();
885             if (PROTECTED_ACTIONS.contains(filterAction)) {
886                 return true;
887             }
888         }
889         return false;
890     }
891 
892     /**
893      * Finds a privileged activity that matches the specified activity names.
894      */
findMatchingActivity( List<ParsedActivity> activityList, ParsedActivity activityInfo)895     private static ParsedActivity findMatchingActivity(
896             List<ParsedActivity> activityList, ParsedActivity activityInfo) {
897         for (ParsedActivity sysActivity : activityList) {
898             if (sysActivity.getName().equals(activityInfo.getName())) {
899                 return sysActivity;
900             }
901             if (sysActivity.getName().equals(activityInfo.getTargetActivity())) {
902                 return sysActivity;
903             }
904             if (sysActivity.getTargetActivity() != null) {
905                 if (sysActivity.getTargetActivity().equals(activityInfo.getName())) {
906                     return sysActivity;
907                 }
908                 if (sysActivity.getTargetActivity().equals(activityInfo.getTargetActivity())) {
909                     return sysActivity;
910                 }
911             }
912         }
913         return null;
914     }
915 
916     /**
917      * Adjusts the priority of the given intent filter according to policy.
918      * <p>
919      * <ul>
920      * <li>The priority for non privileged applications is capped to '0'</li>
921      * <li>The priority for protected actions on privileged applications is capped to '0'</li>
922      * <li>The priority for unbundled updates to privileged applications is capped to the
923      *      priority defined on the system partition</li>
924      * </ul>
925      * <p>
926      * <em>NOTE:</em> There is one exception. For security reasons, the setup wizard is
927      * allowed to obtain any priority on any action.
928      */
adjustPriority(List<ParsedActivity> systemActivities, ParsedActivity activity, ParsedIntentInfo intent, String setupWizardPackage)929     private void adjustPriority(List<ParsedActivity> systemActivities, ParsedActivity activity,
930             ParsedIntentInfo intent, String setupWizardPackage) {
931         // nothing to do; priority is fine as-is
932         if (intent.getPriority() <= 0) {
933             return;
934         }
935 
936         String packageName = activity.getPackageName();
937         AndroidPackage pkg = sPackageManagerInternal.getPackage(packageName);
938 
939         final boolean privilegedApp = pkg.isPrivileged();
940         String className = activity.getClassName();
941         if (!privilegedApp) {
942             // non-privileged applications can never define a priority >0
943             if (DEBUG_FILTERS) {
944                 Slog.i(TAG, "Non-privileged app; cap priority to 0;"
945                         + " package: " + packageName
946                         + " activity: " + className
947                         + " origPrio: " + intent.getPriority());
948             }
949             intent.setPriority(0);
950             return;
951         }
952 
953         if (isProtectedAction(intent)) {
954             if (mDeferProtectedFilters) {
955                 // We can't deal with these just yet. No component should ever obtain a
956                 // >0 priority for a protected actions, with ONE exception -- the setup
957                 // wizard. The setup wizard, however, cannot be known until we're able to
958                 // query it for the category CATEGORY_SETUP_WIZARD. Which we can't do
959                 // until all intent filters have been processed. Chicken, meet egg.
960                 // Let the filter temporarily have a high priority and rectify the
961                 // priorities after all system packages have been scanned.
962                 if (mProtectedFilters == null) {
963                     mProtectedFilters = new ArrayList<>();
964                 }
965                 mProtectedFilters.add(Pair.create(activity, intent));
966                 if (DEBUG_FILTERS) {
967                     Slog.i(TAG, "Protected action; save for later;"
968                             + " package: " + packageName
969                             + " activity: " + className
970                             + " origPrio: " + intent.getPriority());
971                 }
972             } else {
973                 if (DEBUG_FILTERS && setupWizardPackage == null) {
974                     Slog.i(TAG, "No setup wizard;"
975                             + " All protected intents capped to priority 0");
976                 }
977                 if (packageName.equals(setupWizardPackage)) {
978                     if (DEBUG_FILTERS) {
979                         Slog.i(TAG, "Found setup wizard;"
980                                 + " allow priority " + intent.getPriority() + ";"
981                                 + " package: " + packageName
982                                 + " activity: " + className
983                                 + " priority: " + intent.getPriority());
984                     }
985                     // setup wizard gets whatever it wants
986                     return;
987                 }
988                 if (DEBUG_FILTERS) {
989                     Slog.i(TAG, "Protected action; cap priority to 0;"
990                             + " package: " + packageName
991                             + " activity: " + className
992                             + " origPrio: " + intent.getPriority());
993                 }
994                 intent.setPriority(0);
995             }
996             return;
997         }
998 
999         if (systemActivities == null) {
1000             // the system package is not disabled; we're parsing the system partition
1001 
1002             // privileged apps on the system image get whatever priority they request
1003             return;
1004         }
1005 
1006         // privileged app unbundled update ... try to find the same activity
1007 
1008         ParsedActivity foundActivity = findMatchingActivity(systemActivities, activity);
1009         if (foundActivity == null) {
1010             // this is a new activity; it cannot obtain >0 priority
1011             if (DEBUG_FILTERS) {
1012                 Slog.i(TAG, "New activity; cap priority to 0;"
1013                         + " package: " + packageName
1014                         + " activity: " + className
1015                         + " origPrio: " + intent.getPriority());
1016             }
1017             intent.setPriority(0);
1018             return;
1019         }
1020 
1021         // found activity, now check for filter equivalence
1022 
1023         // a shallow copy is enough; we modify the list, not its contents
1024         final List<ParsedIntentInfo> intentListCopy =
1025                 new ArrayList<>(foundActivity.getIntents());
1026 
1027         // find matching action subsets
1028         final Iterator<String> actionsIterator = intent.actionsIterator();
1029         if (actionsIterator != null) {
1030             getIntentListSubset(intentListCopy, IntentFilter::actionsIterator, actionsIterator);
1031             if (intentListCopy.size() == 0) {
1032                 // no more intents to match; we're not equivalent
1033                 if (DEBUG_FILTERS) {
1034                     Slog.i(TAG, "Mismatched action; cap priority to 0;"
1035                             + " package: " + packageName
1036                             + " activity: " + className
1037                             + " origPrio: " + intent.getPriority());
1038                 }
1039                 intent.setPriority(0);
1040                 return;
1041             }
1042         }
1043 
1044         // find matching category subsets
1045         final Iterator<String> categoriesIterator = intent.categoriesIterator();
1046         if (categoriesIterator != null) {
1047             getIntentListSubset(intentListCopy, IntentFilter::categoriesIterator,
1048                     categoriesIterator);
1049             if (intentListCopy.size() == 0) {
1050                 // no more intents to match; we're not equivalent
1051                 if (DEBUG_FILTERS) {
1052                     Slog.i(TAG, "Mismatched category; cap priority to 0;"
1053                             + " package: " + packageName
1054                             + " activity: " + className
1055                             + " origPrio: " + intent.getPriority());
1056                 }
1057                 intent.setPriority(0);
1058                 return;
1059             }
1060         }
1061 
1062         // find matching schemes subsets
1063         final Iterator<String> schemesIterator = intent.schemesIterator();
1064         if (schemesIterator != null) {
1065             getIntentListSubset(intentListCopy, IntentFilter::schemesIterator, schemesIterator);
1066             if (intentListCopy.size() == 0) {
1067                 // no more intents to match; we're not equivalent
1068                 if (DEBUG_FILTERS) {
1069                     Slog.i(TAG, "Mismatched scheme; cap priority to 0;"
1070                             + " package: " + packageName
1071                             + " activity: " + className
1072                             + " origPrio: " + intent.getPriority());
1073                 }
1074                 intent.setPriority(0);
1075                 return;
1076             }
1077         }
1078 
1079         // find matching authorities subsets
1080         final Iterator<IntentFilter.AuthorityEntry> authoritiesIterator =
1081                 intent.authoritiesIterator();
1082         if (authoritiesIterator != null) {
1083             getIntentListSubset(intentListCopy, IntentFilter::authoritiesIterator,
1084                     authoritiesIterator);
1085             if (intentListCopy.size() == 0) {
1086                 // no more intents to match; we're not equivalent
1087                 if (DEBUG_FILTERS) {
1088                     Slog.i(TAG, "Mismatched authority; cap priority to 0;"
1089                             + " package: " + packageName
1090                             + " activity: " + className
1091                             + " origPrio: " + intent.getPriority());
1092                 }
1093                 intent.setPriority(0);
1094                 return;
1095             }
1096         }
1097 
1098         // we found matching filter(s); app gets the max priority of all intents
1099         int cappedPriority = 0;
1100         for (int i = intentListCopy.size() - 1; i >= 0; --i) {
1101             cappedPriority = Math.max(cappedPriority, intentListCopy.get(i).getPriority());
1102         }
1103         if (intent.getPriority() > cappedPriority) {
1104             if (DEBUG_FILTERS) {
1105                 Slog.i(TAG, "Found matching filter(s);"
1106                         + " cap priority to " + cappedPriority + ";"
1107                         + " package: " + packageName
1108                         + " activity: " + className
1109                         + " origPrio: " + intent.getPriority());
1110             }
1111             intent.setPriority(cappedPriority);
1112             return;
1113         }
1114         // all this for nothing; the requested priority was <= what was on the system
1115     }
1116 
1117     @GuardedBy("mLock")
removeAllComponentsLocked(AndroidPackage pkg, boolean chatty)1118     private void removeAllComponentsLocked(AndroidPackage pkg, boolean chatty) {
1119         int componentSize;
1120         StringBuilder r;
1121         int i;
1122 
1123         componentSize = ArrayUtils.size(pkg.getActivities());
1124         r = null;
1125         for (i = 0; i < componentSize; i++) {
1126             ParsedActivity a = pkg.getActivities().get(i);
1127             mActivities.removeActivity(a, "activity");
1128             if (DEBUG_REMOVE && chatty) {
1129                 if (r == null) {
1130                     r = new StringBuilder(256);
1131                 } else {
1132                     r.append(' ');
1133                 }
1134                 r.append(a.getName());
1135             }
1136         }
1137         if (DEBUG_REMOVE && chatty) {
1138             Log.d(TAG, "  Activities: " + (r == null ? "<NONE>" : r));
1139         }
1140 
1141         componentSize = ArrayUtils.size(pkg.getProviders());
1142         r = null;
1143         for (i = 0; i < componentSize; i++) {
1144             ParsedProvider p = pkg.getProviders().get(i);
1145             mProviders.removeProvider(p);
1146             if (p.getAuthority() == null) {
1147                 // Another content provider with this authority existed when this app was
1148                 // installed, so this authority is null. Ignore it as we don't have to
1149                 // unregister the provider.
1150                 continue;
1151             }
1152             String[] names = p.getAuthority().split(";");
1153             for (int j = 0; j < names.length; j++) {
1154                 if (mProvidersByAuthority.get(names[j]) == p) {
1155                     mProvidersByAuthority.remove(names[j]);
1156                     if (DEBUG_REMOVE && chatty) {
1157                         Log.d(TAG, "Unregistered content provider: " + names[j]
1158                                 + ", className = " + p.getName() + ", isSyncable = "
1159                                 + p.isSyncable());
1160                     }
1161                 }
1162             }
1163             if (DEBUG_REMOVE && chatty) {
1164                 if (r == null) {
1165                     r = new StringBuilder(256);
1166                 } else {
1167                     r.append(' ');
1168                 }
1169                 r.append(p.getName());
1170             }
1171         }
1172         if (DEBUG_REMOVE && chatty) {
1173             Log.d(TAG, "  Providers: " + (r == null ? "<NONE>" : r));
1174         }
1175 
1176         componentSize = ArrayUtils.size(pkg.getReceivers());
1177         r = null;
1178         for (i = 0; i < componentSize; i++) {
1179             ParsedActivity a = pkg.getReceivers().get(i);
1180             mReceivers.removeActivity(a, "receiver");
1181             if (DEBUG_REMOVE && chatty) {
1182                 if (r == null) {
1183                     r = new StringBuilder(256);
1184                 } else {
1185                     r.append(' ');
1186                 }
1187                 r.append(a.getName());
1188             }
1189         }
1190         if (DEBUG_REMOVE && chatty) {
1191             Log.d(TAG, "  Receivers: " + (r == null ? "<NONE>" : r));
1192         }
1193 
1194         componentSize = ArrayUtils.size(pkg.getServices());
1195         r = null;
1196         for (i = 0; i < componentSize; i++) {
1197             ParsedService s = pkg.getServices().get(i);
1198             mServices.removeService(s);
1199             if (DEBUG_REMOVE && chatty) {
1200                 if (r == null) {
1201                     r = new StringBuilder(256);
1202                 } else {
1203                     r.append(' ');
1204                 }
1205                 r.append(s.getName());
1206             }
1207         }
1208         if (DEBUG_REMOVE && chatty) {
1209             Log.d(TAG, "  Services: " + (r == null ? "<NONE>" : r));
1210         }
1211     }
1212 
1213     @GuardedBy("mLock")
assertProvidersNotDefinedLocked(AndroidPackage pkg)1214     private void assertProvidersNotDefinedLocked(AndroidPackage pkg)
1215             throws PackageManagerException {
1216         final int providersSize = ArrayUtils.size(pkg.getProviders());
1217         int i;
1218         for (i = 0; i < providersSize; i++) {
1219             ParsedProvider p = pkg.getProviders().get(i);
1220             if (p.getAuthority() != null) {
1221                 final String[] names = p.getAuthority().split(";");
1222                 for (int j = 0; j < names.length; j++) {
1223                     if (mProvidersByAuthority.containsKey(names[j])) {
1224                         final ParsedProvider other = mProvidersByAuthority.get(names[j]);
1225                         final String otherPackageName =
1226                                 (other != null && other.getComponentName() != null)
1227                                         ? other.getComponentName().getPackageName() : "?";
1228                         // if we're installing over the same already-installed package, this is ok
1229                         if (!otherPackageName.equals(pkg.getPackageName())) {
1230                             throw new PackageManagerException(
1231                                     INSTALL_FAILED_CONFLICTING_PROVIDER,
1232                                     "Can't install because provider name " + names[j]
1233                                             + " (in package " + pkg.getPackageName()
1234                                             + ") is already used by " + otherPackageName);
1235                         }
1236                     }
1237                 }
1238             }
1239         }
1240     }
1241 
1242     private abstract static class MimeGroupsAwareIntentResolver<F extends Pair<?
1243             extends ParsedComponent, ParsedIntentInfo>, R>
1244             extends IntentResolver<F, R> {
1245         private final ArrayMap<String, F[]> mMimeGroupToFilter = new ArrayMap<>();
1246         private boolean mIsUpdatingMimeGroup = false;
1247 
1248         // Default constructor
MimeGroupsAwareIntentResolver()1249         MimeGroupsAwareIntentResolver() {
1250         }
1251 
1252         // Copy constructor used in creating snapshots
MimeGroupsAwareIntentResolver(MimeGroupsAwareIntentResolver<F, R> orig)1253         MimeGroupsAwareIntentResolver(MimeGroupsAwareIntentResolver<F, R> orig) {
1254             copyFrom(orig);
1255             copyInto(mMimeGroupToFilter, orig.mMimeGroupToFilter);
1256             mIsUpdatingMimeGroup = orig.mIsUpdatingMimeGroup;
1257         }
1258 
1259         @Override
addFilter(F f)1260         public void addFilter(F f) {
1261             IntentFilter intentFilter = getIntentFilter(f);
1262             applyMimeGroups(f);
1263             super.addFilter(f);
1264 
1265             if (!mIsUpdatingMimeGroup) {
1266                 register_intent_filter(f, intentFilter.mimeGroupsIterator(), mMimeGroupToFilter,
1267                         "      MimeGroup: ");
1268             }
1269         }
1270 
1271         @Override
removeFilterInternal(F f)1272         protected void removeFilterInternal(F f) {
1273             IntentFilter intentFilter = getIntentFilter(f);
1274             if (!mIsUpdatingMimeGroup) {
1275                 unregister_intent_filter(f, intentFilter.mimeGroupsIterator(), mMimeGroupToFilter,
1276                         "      MimeGroup: ");
1277             }
1278 
1279             super.removeFilterInternal(f);
1280             intentFilter.clearDynamicDataTypes();
1281         }
1282 
1283         /**
1284          * Updates MIME group by applying changes to all IntentFilters
1285          * that contain the group and repopulating m*ToFilter maps accordingly
1286          *
1287          * @param packageName package to which MIME group belongs
1288          * @param mimeGroup MIME group to update
1289          * @return true, if any intent filters were changed due to this update
1290          */
updateMimeGroup(String packageName, String mimeGroup)1291         public boolean updateMimeGroup(String packageName, String mimeGroup) {
1292             F[] filters = mMimeGroupToFilter.get(mimeGroup);
1293             int n = filters != null ? filters.length : 0;
1294 
1295             mIsUpdatingMimeGroup = true;
1296             boolean hasChanges = false;
1297             F filter;
1298             for (int i = 0; i < n && (filter = filters[i]) != null; i++) {
1299                 if (isPackageForFilter(packageName, filter)) {
1300                     hasChanges |= updateFilter(filter);
1301                 }
1302             }
1303             mIsUpdatingMimeGroup = false;
1304             return hasChanges;
1305         }
1306 
updateFilter(F f)1307         private boolean updateFilter(F f) {
1308             IntentFilter filter = getIntentFilter(f);
1309             List<String> oldTypes = filter.dataTypes();
1310             removeFilter(f);
1311             addFilter(f);
1312             List<String> newTypes = filter.dataTypes();
1313             return !equalLists(oldTypes, newTypes);
1314         }
1315 
equalLists(List<String> first, List<String> second)1316         private boolean equalLists(List<String> first, List<String> second) {
1317             if (first == null) {
1318                 return second == null;
1319             } else if (second == null) {
1320                 return false;
1321             }
1322 
1323             if (first.size() != second.size()) {
1324                 return false;
1325             }
1326 
1327             Collections.sort(first);
1328             Collections.sort(second);
1329             return first.equals(second);
1330         }
1331 
applyMimeGroups(F f)1332         private void applyMimeGroups(F f) {
1333             IntentFilter filter = getIntentFilter(f);
1334 
1335             for (int i = filter.countMimeGroups() - 1; i >= 0; i--) {
1336                 List<String> mimeTypes = sPackageManagerInternal.getMimeGroup(
1337                         f.first.getPackageName(), filter.getMimeGroup(i));
1338 
1339                 for (int typeIndex = mimeTypes.size() - 1; typeIndex >= 0; typeIndex--) {
1340                     String mimeType = mimeTypes.get(typeIndex);
1341 
1342                     try {
1343                         filter.addDynamicDataType(mimeType);
1344                     } catch (IntentFilter.MalformedMimeTypeException e) {
1345                         if (DEBUG) {
1346                             Slog.w(TAG, "Malformed mime type: " + mimeType, e);
1347                         }
1348                     }
1349                 }
1350             }
1351         }
1352     }
1353 
1354     private static class ActivityIntentResolver
1355             extends MimeGroupsAwareIntentResolver<Pair<ParsedActivity, ParsedIntentInfo>, ResolveInfo> {
1356 
1357         // Default constructor
ActivityIntentResolver()1358         ActivityIntentResolver() {
1359         }
1360 
1361         // Copy constructor used in creating snapshots
ActivityIntentResolver(ActivityIntentResolver orig)1362         ActivityIntentResolver(ActivityIntentResolver orig) {
1363             super(orig);
1364             mActivities.putAll(orig.mActivities);
1365             mFlags = orig.mFlags;
1366         }
1367 
1368         @Override
queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId)1369         public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
1370                 boolean defaultOnly, int userId) {
1371             if (!sUserManager.exists(userId)) return null;
1372             mFlags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0);
1373             return super.queryIntent(intent, resolvedType, defaultOnly, userId);
1374         }
1375 
queryIntent(Intent intent, String resolvedType, int flags, int userId)1376         List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
1377                 int userId) {
1378             if (!sUserManager.exists(userId)) {
1379                 return null;
1380             }
1381             mFlags = flags;
1382             return super.queryIntent(intent, resolvedType,
1383                     (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
1384                     userId);
1385         }
1386 
queryIntentForPackage(Intent intent, String resolvedType, int flags, List<ParsedActivity> packageActivities, int userId)1387         List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
1388                 int flags, List<ParsedActivity> packageActivities, int userId) {
1389             if (!sUserManager.exists(userId)) {
1390                 return null;
1391             }
1392             if (packageActivities == null) {
1393                 return Collections.emptyList();
1394             }
1395             mFlags = flags;
1396             final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
1397             final int activitiesSize = packageActivities.size();
1398             ArrayList<Pair<ParsedActivity, ParsedIntentInfo>[]> listCut =
1399                     new ArrayList<>(activitiesSize);
1400 
1401             List<ParsedIntentInfo> intentFilters;
1402             for (int i = 0; i < activitiesSize; ++i) {
1403                 ParsedActivity activity = packageActivities.get(i);
1404                 intentFilters = activity.getIntents();
1405                 if (!intentFilters.isEmpty()) {
1406                     Pair<ParsedActivity, ParsedIntentInfo>[] array = newArray(intentFilters.size());
1407                     for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
1408                         array[arrayIndex] = Pair.create(activity, intentFilters.get(arrayIndex));
1409                     }
1410                     listCut.add(array);
1411                 }
1412             }
1413             return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
1414         }
1415 
addActivity(ParsedActivity a, String type, List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents)1416         protected void addActivity(ParsedActivity a, String type,
1417                 List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents) {
1418             mActivities.put(a.getComponentName(), a);
1419             if (DEBUG_SHOW_INFO) {
1420                 Log.v(TAG, "  " + type + ":");
1421                 Log.v(TAG, "    Class=" + a.getName());
1422             }
1423             final int intentsSize = a.getIntents().size();
1424             for (int j = 0; j < intentsSize; j++) {
1425                 ParsedIntentInfo intent = a.getIntents().get(j);
1426                 if (newIntents != null && "activity".equals(type)) {
1427                     newIntents.add(Pair.create(a, intent));
1428                 }
1429                 if (DEBUG_SHOW_INFO) {
1430                     Log.v(TAG, "    IntentFilter:");
1431                     intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
1432                 }
1433                 if (!intent.debugCheck()) {
1434                     Log.w(TAG, "==> For Activity " + a.getName());
1435                 }
1436                 addFilter(Pair.create(a, intent));
1437             }
1438         }
1439 
removeActivity(ParsedActivity a, String type)1440         protected void removeActivity(ParsedActivity a, String type) {
1441             mActivities.remove(a.getComponentName());
1442             if (DEBUG_SHOW_INFO) {
1443                 Log.v(TAG, "  " + type + ":");
1444                 Log.v(TAG, "    Class=" + a.getName());
1445             }
1446             final int intentsSize = a.getIntents().size();
1447             for (int j = 0; j < intentsSize; j++) {
1448                 ParsedIntentInfo intent = a.getIntents().get(j);
1449                 if (DEBUG_SHOW_INFO) {
1450                     Log.v(TAG, "    IntentFilter:");
1451                     intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
1452                 }
1453                 removeFilter(Pair.create(a, intent));
1454             }
1455         }
1456 
1457         @Override
allowFilterResult(Pair<ParsedActivity, ParsedIntentInfo> filter, List<ResolveInfo> dest)1458         protected boolean allowFilterResult(Pair<ParsedActivity, ParsedIntentInfo> filter,
1459                 List<ResolveInfo> dest) {
1460             for (int i = dest.size() - 1; i >= 0; --i) {
1461                 ActivityInfo destAi = dest.get(i).activityInfo;
1462                 if (Objects.equals(destAi.name, filter.first.getName())
1463                         && Objects.equals(destAi.packageName, filter.first.getPackageName())) {
1464                     return false;
1465                 }
1466             }
1467             return true;
1468         }
1469 
1470         @Override
newArray(int size)1471         protected Pair<ParsedActivity, ParsedIntentInfo>[] newArray(int size) {
1472             //noinspection unchecked
1473             return (Pair<ParsedActivity, ParsedIntentInfo>[]) new Pair<?, ?>[size];
1474         }
1475 
1476         @Override
isFilterStopped(Pair<ParsedActivity, ParsedIntentInfo> filter, int userId)1477         protected boolean isFilterStopped(Pair<ParsedActivity, ParsedIntentInfo> filter, int userId) {
1478             return ComponentResolver.isFilterStopped(filter, userId);
1479         }
1480 
1481         @Override
isPackageForFilter(String packageName, Pair<ParsedActivity, ParsedIntentInfo> info)1482         protected boolean isPackageForFilter(String packageName,
1483                 Pair<ParsedActivity, ParsedIntentInfo> info) {
1484             return packageName.equals(info.first.getPackageName());
1485         }
1486 
log(String reason, ParsedIntentInfo info, int match, int userId)1487         private void log(String reason, ParsedIntentInfo info, int match,
1488                 int userId) {
1489             Slog.w(TAG, reason
1490                     + "; match: "
1491                     + DebugUtils.flagsToString(IntentFilter.class, "MATCH_", match)
1492                     + "; userId: " + userId
1493                     + "; intent info: " + info);
1494         }
1495 
1496         @Override
newResult(Pair<ParsedActivity, ParsedIntentInfo> pair, int match, int userId)1497         protected ResolveInfo newResult(Pair<ParsedActivity, ParsedIntentInfo> pair,
1498                 int match, int userId) {
1499             ParsedActivity activity = pair.first;
1500             ParsedIntentInfo info = pair.second;
1501 
1502             if (!sUserManager.exists(userId)) {
1503                 if (DEBUG) {
1504                     log("User doesn't exist", info, match, userId);
1505                 }
1506                 return null;
1507             }
1508 
1509             AndroidPackage pkg = sPackageManagerInternal.getPackage(activity.getPackageName());
1510             if (pkg == null) {
1511                 return null;
1512             }
1513 
1514             if (!sPackageManagerInternal.isEnabledAndMatches(activity, mFlags, userId)) {
1515                 if (DEBUG) {
1516                     log("!PackageManagerInternal.isEnabledAndMatches; mFlags="
1517                             + DebugUtils.flagsToString(PackageManager.class, "MATCH_", mFlags),
1518                             info, match, userId);
1519                 }
1520                 return null;
1521             }
1522             PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting(
1523                     activity.getPackageName());
1524             if (ps == null) {
1525                 if (DEBUG) {
1526                     log("info.activity.owner.mExtras == null", info, match, userId);
1527                 }
1528                 return null;
1529             }
1530             final PackageUserState userState = ps.readUserState(userId);
1531             ActivityInfo ai = PackageInfoUtils.generateActivityInfo(pkg, activity, mFlags,
1532                     userState, userId, ps);
1533             if (ai == null) {
1534                 if (DEBUG) {
1535                     log("Failed to create ActivityInfo based on " + activity, info, match,
1536                             userId);
1537                 }
1538                 return null;
1539             }
1540             final boolean matchExplicitlyVisibleOnly =
1541                     (mFlags & PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY) != 0;
1542             final boolean matchVisibleToInstantApp =
1543                     (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
1544             final boolean componentVisible =
1545                     matchVisibleToInstantApp
1546                     && info.isVisibleToInstantApp()
1547                     && (!matchExplicitlyVisibleOnly || info.isExplicitlyVisibleToInstantApp());
1548             final boolean matchInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
1549             // throw out filters that aren't visible to ephemeral apps
1550             if (matchVisibleToInstantApp && !(componentVisible || userState.instantApp)) {
1551                 if (DEBUG) {
1552                     log("Filter(s) not visible to ephemeral apps"
1553                             + "; matchVisibleToInstantApp=" + matchVisibleToInstantApp
1554                             + "; matchInstantApp=" + matchInstantApp
1555                             + "; info.isVisibleToInstantApp()=" + info.isVisibleToInstantApp()
1556                             + "; matchExplicitlyVisibleOnly=" + matchExplicitlyVisibleOnly
1557                             + "; info.isExplicitlyVisibleToInstantApp()="
1558                                     + info.isExplicitlyVisibleToInstantApp(),
1559                             info, match, userId);
1560                 }
1561                 return null;
1562             }
1563             // throw out instant app filters if we're not explicitly requesting them
1564             if (!matchInstantApp && userState.instantApp) {
1565                 if (DEBUG) {
1566                     log("Instant app filter is not explicitly requested", info, match, userId);
1567                 }
1568                 return null;
1569             }
1570             // throw out instant app filters if updates are available; will trigger
1571             // instant app resolution
1572             if (userState.instantApp && ps.isUpdateAvailable()) {
1573                 if (DEBUG) {
1574                     log("Instant app update is available", info, match, userId);
1575                 }
1576                 return null;
1577             }
1578             final ResolveInfo res = new ResolveInfo(info.hasCategory(Intent.CATEGORY_BROWSABLE));
1579             res.activityInfo = ai;
1580             if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
1581                 res.filter = info;
1582             }
1583             res.handleAllWebDataURI = info.handleAllWebDataURI();
1584             res.priority = info.getPriority();
1585             // TODO(b/135203078): This field was unwritten and does nothing
1586 //            res.preferredOrder = pkg.getPreferredOrder();
1587             //System.out.println("Result: " + res.activityInfo.className +
1588             //                   " = " + res.priority);
1589             res.match = match;
1590             res.isDefault = info.isHasDefault();
1591             res.labelRes = info.getLabelRes();
1592             res.nonLocalizedLabel = info.getNonLocalizedLabel();
1593             if (sPackageManagerInternal.userNeedsBadging(userId)) {
1594                 res.noResourceId = true;
1595             } else {
1596                 res.icon = info.getIcon();
1597             }
1598             res.iconResourceId = info.getIcon();
1599             res.system = res.activityInfo.applicationInfo.isSystemApp();
1600             res.isInstantAppAvailable = userState.instantApp;
1601             return res;
1602         }
1603 
1604         @Override
sortResults(List<ResolveInfo> results)1605         protected void sortResults(List<ResolveInfo> results) {
1606             results.sort(RESOLVE_PRIORITY_SORTER);
1607         }
1608 
1609         @Override
dumpFilter(PrintWriter out, String prefix, Pair<ParsedActivity, ParsedIntentInfo> pair)1610         protected void dumpFilter(PrintWriter out, String prefix,
1611                 Pair<ParsedActivity, ParsedIntentInfo> pair) {
1612             ParsedActivity activity = pair.first;
1613             ParsedIntentInfo filter = pair.second;
1614 
1615             out.print(prefix);
1616             out.print(Integer.toHexString(System.identityHashCode(activity)));
1617             out.print(' ');
1618             ComponentName.printShortString(out, activity.getPackageName(),
1619                     activity.getClassName());
1620             out.print(" filter ");
1621             out.println(Integer.toHexString(System.identityHashCode(filter)));
1622         }
1623 
1624         @Override
filterToLabel(Pair<ParsedActivity, ParsedIntentInfo> filter)1625         protected Object filterToLabel(Pair<ParsedActivity, ParsedIntentInfo> filter) {
1626             return filter;
1627         }
1628 
dumpFilterLabel(PrintWriter out, String prefix, Object label, int count)1629         protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
1630             @SuppressWarnings("unchecked") Pair<ParsedActivity, ParsedIntentInfo> pair =
1631                     (Pair<ParsedActivity, ParsedIntentInfo>) label;
1632             out.print(prefix);
1633             out.print(Integer.toHexString(System.identityHashCode(pair.first)));
1634             out.print(' ');
1635             ComponentName.printShortString(out, pair.first.getPackageName(),
1636                     pair.first.getClassName());
1637             if (count > 1) {
1638                 out.print(" ("); out.print(count); out.print(" filters)");
1639             }
1640             out.println();
1641         }
1642 
1643         @Override
getIntentFilter( @onNull Pair<ParsedActivity, ParsedIntentInfo> input)1644         protected IntentFilter getIntentFilter(
1645                 @NonNull Pair<ParsedActivity, ParsedIntentInfo> input) {
1646             return input.second;
1647         }
1648 
getResolveList(AndroidPackage pkg)1649         protected List<ParsedActivity> getResolveList(AndroidPackage pkg) {
1650             return pkg.getActivities();
1651         }
1652 
1653         // Keys are String (activity class name), values are Activity.  This attribute is
1654         // protected because it is accessed directly from ComponentResolver.  That works
1655         // even if the attribute is private, but fails for subclasses of
1656         // ActivityIntentResolver.
1657         protected final ArrayMap<ComponentName, ParsedActivity> mActivities =
1658                 new ArrayMap<>();
1659         private int mFlags;
1660     }
1661 
1662     // Both receivers and activities share a class, but point to different get methods
1663     private static final class ReceiverIntentResolver extends ActivityIntentResolver {
1664 
1665         // Default constructor
ReceiverIntentResolver()1666         ReceiverIntentResolver() {
1667         }
1668 
1669         // Copy constructor used in creating snapshots
ReceiverIntentResolver(ReceiverIntentResolver orig)1670         ReceiverIntentResolver(ReceiverIntentResolver orig) {
1671             super(orig);
1672         }
1673 
1674         @Override
getResolveList(AndroidPackage pkg)1675         protected List<ParsedActivity> getResolveList(AndroidPackage pkg) {
1676             return pkg.getReceivers();
1677         }
1678     }
1679 
1680     private static final class ProviderIntentResolver
1681             extends MimeGroupsAwareIntentResolver<Pair<ParsedProvider, ParsedIntentInfo>, ResolveInfo> {
1682         // Default constructor
ProviderIntentResolver()1683         ProviderIntentResolver() {
1684         }
1685 
1686         // Copy constructor used in creating snapshots
ProviderIntentResolver(ProviderIntentResolver orig)1687         ProviderIntentResolver(ProviderIntentResolver orig) {
1688             super(orig);
1689             mProviders.putAll(orig.mProviders);
1690             mFlags = orig.mFlags;
1691         }
1692 
1693         @Override
queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId)1694         public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
1695                 boolean defaultOnly, int userId) {
1696             mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
1697             return super.queryIntent(intent, resolvedType, defaultOnly, userId);
1698         }
1699 
1700         @Nullable
queryIntent(Intent intent, String resolvedType, int flags, int userId)1701         List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
1702                 int userId) {
1703             if (!sUserManager.exists(userId)) {
1704                 return null;
1705             }
1706             mFlags = flags;
1707             return super.queryIntent(intent, resolvedType,
1708                     (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
1709                     userId);
1710         }
1711 
1712         @Nullable
queryIntentForPackage(Intent intent, String resolvedType, int flags, List<ParsedProvider> packageProviders, int userId)1713         List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
1714                 int flags, List<ParsedProvider> packageProviders, int userId) {
1715             if (!sUserManager.exists(userId)) {
1716                 return null;
1717             }
1718             if (packageProviders == null) {
1719                 return Collections.emptyList();
1720             }
1721             mFlags = flags;
1722             final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
1723             final int providersSize = packageProviders.size();
1724             ArrayList<Pair<ParsedProvider, ParsedIntentInfo>[]> listCut =
1725                     new ArrayList<>(providersSize);
1726 
1727             List<ParsedIntentInfo> intentFilters;
1728             for (int i = 0; i < providersSize; ++i) {
1729                 ParsedProvider provider = packageProviders.get(i);
1730                 intentFilters = provider.getIntents();
1731                 if (!intentFilters.isEmpty()) {
1732                     Pair<ParsedProvider, ParsedIntentInfo>[] array = newArray(intentFilters.size());
1733                     for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
1734                         array[arrayIndex] = Pair.create(provider, intentFilters.get(arrayIndex));
1735                     }
1736                     listCut.add(array);
1737                 }
1738             }
1739             return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
1740         }
1741 
addProvider(ParsedProvider p)1742         void addProvider(ParsedProvider p) {
1743             if (mProviders.containsKey(p.getComponentName())) {
1744                 Slog.w(TAG, "Provider " + p.getComponentName() + " already defined; ignoring");
1745                 return;
1746             }
1747 
1748             mProviders.put(p.getComponentName(), p);
1749             if (DEBUG_SHOW_INFO) {
1750                 Log.v(TAG, "  provider:");
1751                 Log.v(TAG, "    Class=" + p.getName());
1752             }
1753             final int intentsSize = p.getIntents().size();
1754             int j;
1755             for (j = 0; j < intentsSize; j++) {
1756                 ParsedIntentInfo intent = p.getIntents().get(j);
1757                 if (DEBUG_SHOW_INFO) {
1758                     Log.v(TAG, "    IntentFilter:");
1759                     intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
1760                 }
1761                 if (!intent.debugCheck()) {
1762                     Log.w(TAG, "==> For Provider " + p.getName());
1763                 }
1764                 addFilter(Pair.create(p, intent));
1765             }
1766         }
1767 
removeProvider(ParsedProvider p)1768         void removeProvider(ParsedProvider p) {
1769             mProviders.remove(p.getComponentName());
1770             if (DEBUG_SHOW_INFO) {
1771                 Log.v(TAG, "  provider:");
1772                 Log.v(TAG, "    Class=" + p.getName());
1773             }
1774             final int intentsSize = p.getIntents().size();
1775             int j;
1776             for (j = 0; j < intentsSize; j++) {
1777                 ParsedIntentInfo intent = p.getIntents().get(j);
1778                 if (DEBUG_SHOW_INFO) {
1779                     Log.v(TAG, "    IntentFilter:");
1780                     intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
1781                 }
1782                 removeFilter(Pair.create(p, intent));
1783             }
1784         }
1785 
1786         @Override
allowFilterResult(Pair<ParsedProvider, ParsedIntentInfo> filter, List<ResolveInfo> dest)1787         protected boolean allowFilterResult(Pair<ParsedProvider, ParsedIntentInfo> filter,
1788                 List<ResolveInfo> dest) {
1789             for (int i = dest.size() - 1; i >= 0; i--) {
1790                 ProviderInfo destPi = dest.get(i).providerInfo;
1791                 if (Objects.equals(destPi.name, filter.first.getClassName())
1792                         && Objects.equals(destPi.packageName, filter.first.getPackageName())) {
1793                     return false;
1794                 }
1795             }
1796             return true;
1797         }
1798 
1799         @Override
newArray(int size)1800         protected Pair<ParsedProvider, ParsedIntentInfo>[] newArray(int size) {
1801             //noinspection unchecked
1802             return (Pair<ParsedProvider, ParsedIntentInfo>[]) new Pair<?, ?>[size];
1803         }
1804 
1805         @Override
isFilterStopped(Pair<ParsedProvider, ParsedIntentInfo> filter, int userId)1806         protected boolean isFilterStopped(Pair<ParsedProvider, ParsedIntentInfo> filter,
1807                 int userId) {
1808             return ComponentResolver.isFilterStopped(filter, userId);
1809         }
1810 
1811         @Override
isPackageForFilter(String packageName, Pair<ParsedProvider, ParsedIntentInfo> info)1812         protected boolean isPackageForFilter(String packageName,
1813                 Pair<ParsedProvider, ParsedIntentInfo> info) {
1814             return packageName.equals(info.first.getPackageName());
1815         }
1816 
1817         @Override
newResult(Pair<ParsedProvider, ParsedIntentInfo> pair, int match, int userId)1818         protected ResolveInfo newResult(Pair<ParsedProvider, ParsedIntentInfo> pair,
1819                 int match, int userId) {
1820             if (!sUserManager.exists(userId)) {
1821                 return null;
1822             }
1823 
1824             ParsedProvider provider = pair.first;
1825             ParsedIntentInfo filter = pair.second;
1826 
1827             AndroidPackage pkg = sPackageManagerInternal.getPackage(provider.getPackageName());
1828             if (pkg == null) {
1829                 return null;
1830             }
1831 
1832             if (!sPackageManagerInternal.isEnabledAndMatches(provider, mFlags, userId)) {
1833                 return null;
1834             }
1835 
1836             PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting(
1837                     provider.getPackageName());
1838             if (ps == null) {
1839                 return null;
1840             }
1841             final PackageUserState userState = ps.readUserState(userId);
1842             final boolean matchVisibleToInstantApp = (mFlags
1843                     & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
1844             final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
1845             // throw out filters that aren't visible to instant applications
1846             if (matchVisibleToInstantApp
1847                     && !(filter.isVisibleToInstantApp() || userState.instantApp)) {
1848                 return null;
1849             }
1850             // throw out instant application filters if we're not explicitly requesting them
1851             if (!isInstantApp && userState.instantApp) {
1852                 return null;
1853             }
1854             // throw out instant application filters if updates are available; will trigger
1855             // instant application resolution
1856             if (userState.instantApp && ps.isUpdateAvailable()) {
1857                 return null;
1858             }
1859             final ApplicationInfo appInfo = PackageInfoUtils.generateApplicationInfo(
1860                     pkg, mFlags, userState, userId, ps);
1861             if (appInfo == null) {
1862                 return null;
1863             }
1864             ProviderInfo pi = PackageInfoUtils.generateProviderInfo(pkg, provider, mFlags,
1865                     userState, appInfo, userId, ps);
1866             if (pi == null) {
1867                 return null;
1868             }
1869             final ResolveInfo res = new ResolveInfo();
1870             res.providerInfo = pi;
1871             if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
1872                 res.filter = filter;
1873             }
1874             res.priority = filter.getPriority();
1875             // TODO(b/135203078): This field was unwritten and does nothing
1876 //            res.preferredOrder = pkg.getPreferredOrder();
1877             res.match = match;
1878             res.isDefault = filter.isHasDefault();
1879             res.labelRes = filter.getLabelRes();
1880             res.nonLocalizedLabel = filter.getNonLocalizedLabel();
1881             res.icon = filter.getIcon();
1882             res.system = res.providerInfo.applicationInfo.isSystemApp();
1883             return res;
1884         }
1885 
1886         @Override
sortResults(List<ResolveInfo> results)1887         protected void sortResults(List<ResolveInfo> results) {
1888             results.sort(RESOLVE_PRIORITY_SORTER);
1889         }
1890 
1891         @Override
dumpFilter(PrintWriter out, String prefix, Pair<ParsedProvider, ParsedIntentInfo> pair)1892         protected void dumpFilter(PrintWriter out, String prefix,
1893                 Pair<ParsedProvider, ParsedIntentInfo> pair) {
1894             ParsedProvider provider = pair.first;
1895             ParsedIntentInfo filter = pair.second;
1896 
1897             out.print(prefix);
1898             out.print(Integer.toHexString(System.identityHashCode(provider)));
1899             out.print(' ');
1900             ComponentName.printShortString(out, provider.getPackageName(), provider.getClassName());
1901             out.print(" filter ");
1902             out.println(Integer.toHexString(System.identityHashCode(filter)));
1903         }
1904 
1905         @Override
filterToLabel(Pair<ParsedProvider, ParsedIntentInfo> filter)1906         protected Object filterToLabel(Pair<ParsedProvider, ParsedIntentInfo> filter) {
1907             return filter;
1908         }
1909 
dumpFilterLabel(PrintWriter out, String prefix, Object label, int count)1910         protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
1911             @SuppressWarnings("unchecked") final Pair<ParsedProvider, ParsedIntentInfo> pair =
1912                     (Pair<ParsedProvider, ParsedIntentInfo>) label;
1913             out.print(prefix);
1914             out.print(Integer.toHexString(System.identityHashCode(pair.first)));
1915             out.print(' ');
1916             ComponentName.printShortString(out, pair.first.getPackageName(),
1917                     pair.first.getClassName());
1918             if (count > 1) {
1919                 out.print(" (");
1920                 out.print(count);
1921                 out.print(" filters)");
1922             }
1923             out.println();
1924         }
1925 
1926         @Override
getIntentFilter( @onNull Pair<ParsedProvider, ParsedIntentInfo> input)1927         protected IntentFilter getIntentFilter(
1928                 @NonNull Pair<ParsedProvider, ParsedIntentInfo> input) {
1929             return input.second;
1930         }
1931 
1932         private final ArrayMap<ComponentName, ParsedProvider> mProviders = new ArrayMap<>();
1933         private int mFlags;
1934     }
1935 
1936     private static final class ServiceIntentResolver
1937             extends MimeGroupsAwareIntentResolver<Pair<ParsedService, ParsedIntentInfo>, ResolveInfo> {
1938         // Default constructor
ServiceIntentResolver()1939         ServiceIntentResolver() {
1940         }
1941 
1942         // Copy constructor used in creating snapshots
ServiceIntentResolver(ServiceIntentResolver orig)1943         ServiceIntentResolver(ServiceIntentResolver orig) {
1944             copyFrom(orig);
1945             mServices.putAll(orig.mServices);
1946             mFlags = orig.mFlags;
1947         }
1948 
1949         @Override
queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId)1950         public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
1951                 boolean defaultOnly, int userId) {
1952             mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
1953             return super.queryIntent(intent, resolvedType, defaultOnly, userId);
1954         }
1955 
queryIntent(Intent intent, String resolvedType, int flags, int userId)1956         List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
1957                 int userId) {
1958             if (!sUserManager.exists(userId)) return null;
1959             mFlags = flags;
1960             return super.queryIntent(intent, resolvedType,
1961                     (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
1962                     userId);
1963         }
1964 
queryIntentForPackage(Intent intent, String resolvedType, int flags, List<ParsedService> packageServices, int userId)1965         List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
1966                 int flags, List<ParsedService> packageServices, int userId) {
1967             if (!sUserManager.exists(userId)) return null;
1968             if (packageServices == null) {
1969                 return Collections.emptyList();
1970             }
1971             mFlags = flags;
1972             final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
1973             final int servicesSize = packageServices.size();
1974             ArrayList<Pair<ParsedService, ParsedIntentInfo>[]> listCut =
1975                     new ArrayList<>(servicesSize);
1976 
1977             List<ParsedIntentInfo> intentFilters;
1978             for (int i = 0; i < servicesSize; ++i) {
1979                 ParsedService service = packageServices.get(i);
1980                 intentFilters = service.getIntents();
1981                 if (intentFilters.size() > 0) {
1982                     Pair<ParsedService, ParsedIntentInfo>[] array = newArray(intentFilters.size());
1983                     for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
1984                         array[arrayIndex] = Pair.create(service, intentFilters.get(arrayIndex));
1985                     }
1986                     listCut.add(array);
1987                 }
1988             }
1989             return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
1990         }
1991 
addService(ParsedService s)1992         void addService(ParsedService s) {
1993             mServices.put(s.getComponentName(), s);
1994             if (DEBUG_SHOW_INFO) {
1995                 Log.v(TAG, "  service:");
1996                 Log.v(TAG, "    Class=" + s.getName());
1997             }
1998             final int intentsSize = s.getIntents().size();
1999             int j;
2000             for (j = 0; j < intentsSize; j++) {
2001                 ParsedIntentInfo intent = s.getIntents().get(j);
2002                 if (DEBUG_SHOW_INFO) {
2003                     Log.v(TAG, "    IntentFilter:");
2004                     intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
2005                 }
2006                 if (!intent.debugCheck()) {
2007                     Log.w(TAG, "==> For Service " + s.getName());
2008                 }
2009                 addFilter(Pair.create(s, intent));
2010             }
2011         }
2012 
removeService(ParsedService s)2013         void removeService(ParsedService s) {
2014             mServices.remove(s.getComponentName());
2015             if (DEBUG_SHOW_INFO) {
2016                 Log.v(TAG, "  service:");
2017                 Log.v(TAG, "    Class=" + s.getName());
2018             }
2019             final int intentsSize = s.getIntents().size();
2020             int j;
2021             for (j = 0; j < intentsSize; j++) {
2022                 ParsedIntentInfo intent = s.getIntents().get(j);
2023                 if (DEBUG_SHOW_INFO) {
2024                     Log.v(TAG, "    IntentFilter:");
2025                     intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
2026                 }
2027                 removeFilter(Pair.create(s, intent));
2028             }
2029         }
2030 
2031         @Override
allowFilterResult(Pair<ParsedService, ParsedIntentInfo> filter, List<ResolveInfo> dest)2032         protected boolean allowFilterResult(Pair<ParsedService, ParsedIntentInfo> filter,
2033                 List<ResolveInfo> dest) {
2034             for (int i = dest.size() - 1; i >= 0; --i) {
2035                 ServiceInfo destAi = dest.get(i).serviceInfo;
2036                 if (Objects.equals(destAi.name, filter.first.getClassName())
2037                         && Objects.equals(destAi.packageName, filter.first.getPackageName())) {
2038                     return false;
2039                 }
2040             }
2041             return true;
2042         }
2043 
2044         @Override
newArray(int size)2045         protected Pair<ParsedService, ParsedIntentInfo>[] newArray(int size) {
2046             //noinspection unchecked
2047             return (Pair<ParsedService, ParsedIntentInfo>[]) new Pair<?, ?>[size];
2048         }
2049 
2050         @Override
isFilterStopped(Pair<ParsedService, ParsedIntentInfo> filter, int userId)2051         protected boolean isFilterStopped(Pair<ParsedService, ParsedIntentInfo> filter, int userId) {
2052             return ComponentResolver.isFilterStopped(filter, userId);
2053         }
2054 
2055         @Override
isPackageForFilter(String packageName, Pair<ParsedService, ParsedIntentInfo> info)2056         protected boolean isPackageForFilter(String packageName,
2057                 Pair<ParsedService, ParsedIntentInfo> info) {
2058             return packageName.equals(info.first.getPackageName());
2059         }
2060 
2061         @Override
newResult(Pair<ParsedService, ParsedIntentInfo> pair, int match, int userId)2062         protected ResolveInfo newResult(Pair<ParsedService, ParsedIntentInfo> pair, int match,
2063                 int userId) {
2064             if (!sUserManager.exists(userId)) return null;
2065 
2066             ParsedService service = pair.first;
2067             ParsedIntentInfo filter = pair.second;
2068 
2069             AndroidPackage pkg = sPackageManagerInternal.getPackage(service.getPackageName());
2070             if (pkg == null) {
2071                 return null;
2072             }
2073 
2074             if (!sPackageManagerInternal.isEnabledAndMatches(service, mFlags, userId)) {
2075                 return null;
2076             }
2077 
2078             PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting(
2079                     service.getPackageName());
2080             if (ps == null) {
2081                 return null;
2082             }
2083             final PackageUserState userState = ps.readUserState(userId);
2084             ServiceInfo si = PackageInfoUtils.generateServiceInfo(pkg, service, mFlags,
2085                     userState, userId, ps);
2086             if (si == null) {
2087                 return null;
2088             }
2089             final boolean matchVisibleToInstantApp =
2090                     (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
2091             final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
2092             // throw out filters that aren't visible to ephemeral apps
2093             if (matchVisibleToInstantApp
2094                     && !(filter.isVisibleToInstantApp() || userState.instantApp)) {
2095                 return null;
2096             }
2097             // throw out ephemeral filters if we're not explicitly requesting them
2098             if (!isInstantApp && userState.instantApp) {
2099                 return null;
2100             }
2101             // throw out instant app filters if updates are available; will trigger
2102             // instant app resolution
2103             if (userState.instantApp && ps.isUpdateAvailable()) {
2104                 return null;
2105             }
2106             final ResolveInfo res = new ResolveInfo();
2107             res.serviceInfo = si;
2108             if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
2109                 res.filter = filter;
2110             }
2111             res.priority = filter.getPriority();
2112             // TODO(b/135203078): This field was unwritten and does nothing
2113 //            res.preferredOrder = pkg.getPreferredOrder();
2114             res.match = match;
2115             res.isDefault = filter.isHasDefault();
2116             res.labelRes = filter.getLabelRes();
2117             res.nonLocalizedLabel = filter.getNonLocalizedLabel();
2118             res.icon = filter.getIcon();
2119             res.system = res.serviceInfo.applicationInfo.isSystemApp();
2120             return res;
2121         }
2122 
2123         @Override
sortResults(List<ResolveInfo> results)2124         protected void sortResults(List<ResolveInfo> results) {
2125             results.sort(RESOLVE_PRIORITY_SORTER);
2126         }
2127 
2128         @Override
dumpFilter(PrintWriter out, String prefix, Pair<ParsedService, ParsedIntentInfo> pair)2129         protected void dumpFilter(PrintWriter out, String prefix,
2130                 Pair<ParsedService, ParsedIntentInfo> pair) {
2131             ParsedService service = pair.first;
2132             ParsedIntentInfo filter = pair.second;
2133 
2134             out.print(prefix);
2135             out.print(Integer.toHexString(System.identityHashCode(service)));
2136             out.print(' ');
2137             ComponentName.printShortString(out, service.getPackageName(), service.getClassName());
2138             out.print(" filter ");
2139             out.print(Integer.toHexString(System.identityHashCode(filter)));
2140             if (service.getPermission() != null) {
2141                 out.print(" permission "); out.println(service.getPermission());
2142             } else {
2143                 out.println();
2144             }
2145         }
2146 
2147         @Override
filterToLabel(Pair<ParsedService, ParsedIntentInfo> filter)2148         protected Object filterToLabel(Pair<ParsedService, ParsedIntentInfo> filter) {
2149             return filter;
2150         }
2151 
dumpFilterLabel(PrintWriter out, String prefix, Object label, int count)2152         protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
2153             @SuppressWarnings("unchecked") final Pair<ParsedService, ParsedIntentInfo> pair =
2154                     (Pair<ParsedService, ParsedIntentInfo>) label;
2155             out.print(prefix);
2156             out.print(Integer.toHexString(System.identityHashCode(pair.first)));
2157             out.print(' ');
2158             ComponentName.printShortString(out, pair.first.getPackageName(),
2159                     pair.first.getClassName());
2160             if (count > 1) {
2161                 out.print(" ("); out.print(count); out.print(" filters)");
2162             }
2163             out.println();
2164         }
2165 
2166         @Override
getIntentFilter( @onNull Pair<ParsedService, ParsedIntentInfo> input)2167         protected IntentFilter getIntentFilter(
2168                 @NonNull Pair<ParsedService, ParsedIntentInfo> input) {
2169             return input.second;
2170         }
2171 
2172         // Keys are String (activity class name), values are Activity.
2173         private final ArrayMap<ComponentName, ParsedService> mServices = new ArrayMap<>();
2174         private int mFlags;
2175     }
2176 
2177     static final class InstantAppIntentResolver
2178             extends IntentResolver<AuxiliaryResolveInfo.AuxiliaryFilter,
2179             AuxiliaryResolveInfo.AuxiliaryFilter> {
2180         /**
2181          * The result that has the highest defined order. Ordering applies on a
2182          * per-package basis. Mapping is from package name to Pair of order and
2183          * EphemeralResolveInfo.
2184          * <p>
2185          * NOTE: This is implemented as a field variable for convenience and efficiency.
2186          * By having a field variable, we're able to track filter ordering as soon as
2187          * a non-zero order is defined. Otherwise, multiple loops across the result set
2188          * would be needed to apply ordering. If the intent resolver becomes re-entrant,
2189          * this needs to be contained entirely within {@link #filterResults}.
2190          */
2191         final ArrayMap<String, Pair<Integer, InstantAppResolveInfo>> mOrderResult =
2192                 new ArrayMap<>();
2193 
2194         @Override
newArray(int size)2195         protected AuxiliaryResolveInfo.AuxiliaryFilter[] newArray(int size) {
2196             return new AuxiliaryResolveInfo.AuxiliaryFilter[size];
2197         }
2198 
2199         @Override
isPackageForFilter(String packageName, AuxiliaryResolveInfo.AuxiliaryFilter responseObj)2200         protected boolean isPackageForFilter(String packageName,
2201                 AuxiliaryResolveInfo.AuxiliaryFilter responseObj) {
2202             return true;
2203         }
2204 
2205         @Override
newResult( AuxiliaryResolveInfo.AuxiliaryFilter responseObj, int match, int userId)2206         protected AuxiliaryResolveInfo.AuxiliaryFilter newResult(
2207                 AuxiliaryResolveInfo.AuxiliaryFilter responseObj, int match, int userId) {
2208             if (!sUserManager.exists(userId)) {
2209                 return null;
2210             }
2211             final String packageName = responseObj.resolveInfo.getPackageName();
2212             final Integer order = responseObj.getOrder();
2213             final Pair<Integer, InstantAppResolveInfo> lastOrderResult =
2214                     mOrderResult.get(packageName);
2215             // ordering is enabled and this item's order isn't high enough
2216             if (lastOrderResult != null && lastOrderResult.first >= order) {
2217                 return null;
2218             }
2219             final InstantAppResolveInfo res = responseObj.resolveInfo;
2220             if (order > 0) {
2221                 // non-zero order, enable ordering
2222                 mOrderResult.put(packageName, new Pair<>(order, res));
2223             }
2224             return responseObj;
2225         }
2226 
2227         @Override
filterResults(List<AuxiliaryResolveInfo.AuxiliaryFilter> results)2228         protected void filterResults(List<AuxiliaryResolveInfo.AuxiliaryFilter> results) {
2229             // only do work if ordering is enabled [most of the time it won't be]
2230             if (mOrderResult.size() == 0) {
2231                 return;
2232             }
2233             int resultSize = results.size();
2234             for (int i = 0; i < resultSize; i++) {
2235                 final InstantAppResolveInfo info = results.get(i).resolveInfo;
2236                 final String packageName = info.getPackageName();
2237                 final Pair<Integer, InstantAppResolveInfo> savedInfo =
2238                         mOrderResult.get(packageName);
2239                 if (savedInfo == null) {
2240                     // package doesn't having ordering
2241                     continue;
2242                 }
2243                 if (savedInfo.second == info) {
2244                     // circled back to the highest ordered item; remove from order list
2245                     mOrderResult.remove(packageName);
2246                     if (mOrderResult.size() == 0) {
2247                         // no more ordered items
2248                         break;
2249                     }
2250                     continue;
2251                 }
2252                 // item has a worse order, remove it from the result list
2253                 results.remove(i);
2254                 resultSize--;
2255                 i--;
2256             }
2257         }
2258 
2259         @Override
getIntentFilter( @onNull AuxiliaryResolveInfo.AuxiliaryFilter input)2260         protected IntentFilter getIntentFilter(
2261                 @NonNull AuxiliaryResolveInfo.AuxiliaryFilter input) {
2262             return input;
2263         }
2264     }
2265 
isFilterStopped(Pair<? extends ParsedComponent, ParsedIntentInfo> pair, int userId)2266     private static boolean isFilterStopped(Pair<? extends ParsedComponent, ParsedIntentInfo> pair,
2267             int userId) {
2268         if (!sUserManager.exists(userId)) {
2269             return true;
2270         }
2271 
2272         AndroidPackage pkg = sPackageManagerInternal.getPackage(pair.first.getPackageName());
2273         if (pkg == null) {
2274             return false;
2275         }
2276 
2277         PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting(
2278                 pair.first.getPackageName());
2279         if (ps == null) {
2280             return false;
2281         }
2282 
2283         // System apps are never considered stopped for purposes of
2284         // filtering, because there may be no way for the user to
2285         // actually re-launch them.
2286         return !ps.isSystem() && ps.getStopped(userId);
2287     }
2288 
2289     /** Generic to create an {@link Iterator} for a data type */
2290     static class IterGenerator<E> {
generate(ParsedIntentInfo info)2291         public Iterator<E> generate(ParsedIntentInfo info) {
2292             return null;
2293         }
2294     }
2295 
2296     /** Create an {@link Iterator} for intent actions */
2297     static class ActionIterGenerator extends IterGenerator<String> {
2298         @Override
generate(ParsedIntentInfo info)2299         public Iterator<String> generate(ParsedIntentInfo info) {
2300             return info.actionsIterator();
2301         }
2302     }
2303 
2304     /** Create an {@link Iterator} for intent categories */
2305     static class CategoriesIterGenerator extends IterGenerator<String> {
2306         @Override
generate(ParsedIntentInfo info)2307         public Iterator<String> generate(ParsedIntentInfo info) {
2308             return info.categoriesIterator();
2309         }
2310     }
2311 
2312     /** Create an {@link Iterator} for intent schemes */
2313     static class SchemesIterGenerator extends IterGenerator<String> {
2314         @Override
generate(ParsedIntentInfo info)2315         public Iterator<String> generate(ParsedIntentInfo info) {
2316             return info.schemesIterator();
2317         }
2318     }
2319 
2320     /** Create an {@link Iterator} for intent authorities */
2321     static class AuthoritiesIterGenerator extends IterGenerator<IntentFilter.AuthorityEntry> {
2322         @Override
generate(ParsedIntentInfo info)2323         public Iterator<IntentFilter.AuthorityEntry> generate(ParsedIntentInfo info) {
2324             return info.authoritiesIterator();
2325         }
2326     }
2327 
2328     /**
2329      * Removes MIME type from the group, by delegating to IntentResolvers
2330      * @return true if any intent filters were changed due to this update
2331      */
updateMimeGroup(String packageName, String group)2332     boolean updateMimeGroup(String packageName, String group) {
2333         boolean hasChanges = false;
2334         synchronized (mLock) {
2335             hasChanges |= mActivities.updateMimeGroup(packageName, group);
2336             hasChanges |= mProviders.updateMimeGroup(packageName, group);
2337             hasChanges |= mReceivers.updateMimeGroup(packageName, group);
2338             hasChanges |= mServices.updateMimeGroup(packageName, group);
2339             if (hasChanges) {
2340                 onChanged();
2341             }
2342         }
2343         return hasChanges;
2344     }
2345 }
2346