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