1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.pm.resolution;
18 
19 import static android.content.pm.PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
20 
21 import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
22 import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
23 
24 import android.annotation.NonNull;
25 import android.annotation.Nullable;
26 import android.annotation.UserIdInt;
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.ProviderInfo;
36 import android.content.pm.ResolveInfo;
37 import android.content.pm.ServiceInfo;
38 import android.os.UserHandle;
39 import android.util.ArrayMap;
40 import android.util.ArraySet;
41 import android.util.DebugUtils;
42 import android.util.Log;
43 import android.util.LogPrinter;
44 import android.util.Pair;
45 import android.util.Slog;
46 
47 import com.android.internal.annotations.GuardedBy;
48 import com.android.internal.pm.pkg.component.ComponentMutateUtils;
49 import com.android.internal.pm.pkg.component.ParsedActivity;
50 import com.android.internal.pm.pkg.component.ParsedComponent;
51 import com.android.internal.pm.pkg.component.ParsedIntentInfo;
52 import com.android.internal.pm.pkg.component.ParsedMainComponent;
53 import com.android.internal.pm.pkg.component.ParsedProvider;
54 import com.android.internal.pm.pkg.component.ParsedProviderImpl;
55 import com.android.internal.pm.pkg.component.ParsedService;
56 import com.android.internal.util.ArrayUtils;
57 import com.android.server.IntentResolver;
58 import com.android.server.pm.Computer;
59 import com.android.server.pm.PackageManagerException;
60 import com.android.server.pm.UserManagerService;
61 import com.android.server.pm.UserNeedsBadgingCache;
62 import com.android.server.pm.parsing.PackageInfoUtils;
63 import com.android.server.pm.pkg.AndroidPackage;
64 import com.android.server.pm.pkg.PackageStateInternal;
65 import com.android.server.pm.pkg.PackageStateUtils;
66 import com.android.server.pm.pkg.PackageUserStateInternal;
67 import com.android.server.pm.snapshot.PackageDataSnapshot;
68 import com.android.server.utils.Snappable;
69 import com.android.server.utils.SnapshotCache;
70 
71 import java.io.PrintWriter;
72 import java.util.ArrayList;
73 import java.util.Collection;
74 import java.util.Collections;
75 import java.util.Comparator;
76 import java.util.Iterator;
77 import java.util.List;
78 import java.util.Objects;
79 import java.util.Set;
80 import java.util.function.Function;
81 
82 /** Resolves all Android component types [activities, services, providers and receivers]. */
83 public class ComponentResolver extends ComponentResolverLocked implements
84         Snappable<ComponentResolverApi> {
85     private static final boolean DEBUG = false;
86     private static final String TAG = "PackageManager";
87     private static final boolean DEBUG_FILTERS = false;
88     private static final boolean DEBUG_SHOW_INFO = false;
89 
90     // Convenience function to report that this object has changed.
onChanged()91     private void onChanged() {
92         dispatchChange(this);
93     }
94 
95     /**
96      * The set of all protected actions [i.e. those actions for which a high priority
97      * intent filter is disallowed].
98      */
99     private static final Set<String> PROTECTED_ACTIONS = new ArraySet<>();
100     static {
101         PROTECTED_ACTIONS.add(Intent.ACTION_SEND);
102         PROTECTED_ACTIONS.add(Intent.ACTION_SENDTO);
103         PROTECTED_ACTIONS.add(Intent.ACTION_SEND_MULTIPLE);
104         PROTECTED_ACTIONS.add(Intent.ACTION_VIEW);
105     }
106 
107     public static final Comparator<ResolveInfo> RESOLVE_PRIORITY_SORTER = (r1, r2) -> {
108         int v1 = r1.priority;
109         int v2 = r2.priority;
110         //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
111         if (v1 != v2) {
112             return (v1 > v2) ? -1 : 1;
113         }
114         v1 = r1.preferredOrder;
115         v2 = r2.preferredOrder;
116         if (v1 != v2) {
117             return (v1 > v2) ? -1 : 1;
118         }
119         if (r1.isDefault != r2.isDefault) {
120             return r1.isDefault ? -1 : 1;
121         }
122         v1 = r1.match;
123         v2 = r2.match;
124         //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
125         if (v1 != v2) {
126             return (v1 > v2) ? -1 : 1;
127         }
128         if (r1.system != r2.system) {
129             return r1.system ? -1 : 1;
130         }
131         if (r1.activityInfo != null) {
132             return r1.activityInfo.packageName.compareTo(r2.activityInfo.packageName);
133         }
134         if (r1.serviceInfo != null) {
135             return r1.serviceInfo.packageName.compareTo(r2.serviceInfo.packageName);
136         }
137         if (r1.providerInfo != null) {
138             return r1.providerInfo.packageName.compareTo(r2.providerInfo.packageName);
139         }
140         return 0;
141     };
142 
143     /** Whether or not processing protected filters should be deferred. */
144     boolean mDeferProtectedFilters = true;
145 
146     /**
147      * Tracks high priority intent filters for protected actions. During boot, certain
148      * filter actions are protected and should never be allowed to have a high priority
149      * intent filter for them. However, there is one, and only one exception -- the
150      * setup wizard. It must be able to define a high priority intent filter for these
151      * actions to ensure there are no escapes from the wizard. We need to delay processing
152      * of these during boot as we need to inspect at all of the intent filters on the
153      * /system partition in order to know which component is the setup wizard. This can
154      * only ever be non-empty if {@link #mDeferProtectedFilters} is {@code true}.
155      *
156      * This is a pair of component package name to actual filter, because we don't store the
157      * name inside the filter. It's technically independent of the component it's contained in.
158      */
159     List<Pair<ParsedMainComponent, ParsedIntentInfo>> mProtectedFilters;
160 
ComponentResolver(@onNull UserManagerService userManager, @NonNull UserNeedsBadgingCache userNeedsBadgingCache)161     public ComponentResolver(@NonNull UserManagerService userManager,
162             @NonNull UserNeedsBadgingCache userNeedsBadgingCache) {
163         super(userManager);
164         mActivities = new ActivityIntentResolver(userManager, userNeedsBadgingCache);
165         mProviders = new ProviderIntentResolver(userManager);
166         mReceivers = new ReceiverIntentResolver(userManager, userNeedsBadgingCache);
167         mServices = new ServiceIntentResolver(userManager);
168         mProvidersByAuthority = new ArrayMap<>();
169         mDeferProtectedFilters = true;
170 
171         mSnapshot = new SnapshotCache<>(this, this) {
172                 @Override
173                 public ComponentResolverApi createSnapshot() {
174                     synchronized (mLock) {
175                         return new ComponentResolverSnapshot(ComponentResolver.this,
176                                 userNeedsBadgingCache);
177                     }
178                 }};
179     }
180 
181     final SnapshotCache<ComponentResolverApi> mSnapshot;
182 
183     /**
184      * Create a snapshot.
185      */
snapshot()186     public ComponentResolverApi snapshot() {
187         return mSnapshot.snapshot();
188     }
189 
190     /** Add all components defined in the given package to the internal structures. */
addAllComponents(AndroidPackage pkg, boolean chatty, @Nullable String setupWizardPackage, @NonNull Computer computer)191     public void addAllComponents(AndroidPackage pkg, boolean chatty,
192             @Nullable String setupWizardPackage, @NonNull Computer computer) {
193         final ArrayList<Pair<ParsedActivity, ParsedIntentInfo>> newIntents = new ArrayList<>();
194         synchronized (mLock) {
195             addActivitiesLocked(computer, pkg, newIntents, chatty);
196             addReceiversLocked(computer, pkg, chatty);
197             addProvidersLocked(computer, pkg, chatty);
198             addServicesLocked(computer, pkg, chatty);
199             onChanged();
200         }
201 
202         for (int i = newIntents.size() - 1; i >= 0; --i) {
203             final Pair<ParsedActivity, ParsedIntentInfo> pair = newIntents.get(i);
204             final PackageStateInternal disabledPkgSetting = computer
205                     .getDisabledSystemPackage(pair.first.getPackageName());
206             final AndroidPackage disabledPkg =
207                     disabledPkgSetting == null ? null : disabledPkgSetting.getPkg();
208             final List<ParsedActivity> systemActivities =
209                     disabledPkg != null ? disabledPkg.getActivities() : null;
210             adjustPriority(computer, systemActivities, pair.first, pair.second, setupWizardPackage);
211             onChanged();
212         }
213     }
214 
215     /** Removes all components defined in the given package from the internal structures. */
removeAllComponents(AndroidPackage pkg, boolean chatty)216     public void removeAllComponents(AndroidPackage pkg, boolean chatty) {
217         synchronized (mLock) {
218             removeAllComponentsLocked(pkg, chatty);
219             onChanged();
220         }
221     }
222 
223     /**
224      * Reprocess any protected filters that have been deferred. At this point, we've scanned
225      * all of the filters defined on the /system partition and know the special components.
226      */
fixProtectedFilterPriorities(@ullable String setupWizardPackage)227     public void fixProtectedFilterPriorities(@Nullable String setupWizardPackage) {
228         synchronized (mLock) {
229             if (!mDeferProtectedFilters) {
230                 return;
231             }
232             mDeferProtectedFilters = false;
233 
234             if (mProtectedFilters == null || mProtectedFilters.size() == 0) {
235                 return;
236             }
237             final List<Pair<ParsedMainComponent, ParsedIntentInfo>> protectedFilters =
238                     mProtectedFilters;
239             mProtectedFilters = null;
240 
241             if (DEBUG_FILTERS && setupWizardPackage == null) {
242                 Slog.i(TAG, "No setup wizard;"
243                         + " All protected intents capped to priority 0");
244             }
245             for (int i = protectedFilters.size() - 1; i >= 0; --i) {
246                 final Pair<ParsedMainComponent, ParsedIntentInfo> pair = protectedFilters.get(i);
247                 ParsedMainComponent component = pair.first;
248                 ParsedIntentInfo intentInfo = pair.second;
249                 IntentFilter filter = intentInfo.getIntentFilter();
250                 String packageName = component.getPackageName();
251                 String className = component.getClassName();
252                 if (packageName.equals(setupWizardPackage)) {
253                     if (DEBUG_FILTERS) {
254                         Slog.i(TAG, "Found setup wizard;"
255                                 + " allow priority " + filter.getPriority() + ";"
256                                 + " package: " + packageName
257                                 + " activity: " + className
258                                 + " priority: " + filter.getPriority());
259                     }
260                     // skip setup wizard; allow it to keep the high priority filter
261                     continue;
262                 }
263                 if (DEBUG_FILTERS) {
264                     Slog.i(TAG, "Protected action; cap priority to 0;"
265                             + " package: " + packageName
266                             + " activity: " + className
267                             + " origPrio: " + filter.getPriority());
268                 }
269                 filter.setPriority(0);
270             }
271             onChanged();
272         }
273     }
274 
275     @GuardedBy("mLock")
addActivitiesLocked(@onNull Computer computer, AndroidPackage pkg, List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents, boolean chatty)276     private void addActivitiesLocked(@NonNull Computer computer, AndroidPackage pkg,
277             List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents, boolean chatty) {
278         final int activitiesSize = ArrayUtils.size(pkg.getActivities());
279         StringBuilder r = null;
280         for (int i = 0; i < activitiesSize; i++) {
281             ParsedActivity a = pkg.getActivities().get(i);
282             mActivities.addActivity(computer, a, "activity", newIntents);
283             if (DEBUG_PACKAGE_SCANNING && chatty) {
284                 if (r == null) {
285                     r = new StringBuilder(256);
286                 } else {
287                     r.append(' ');
288                 }
289                 r.append(a.getName());
290             }
291         }
292         if (DEBUG_PACKAGE_SCANNING && chatty) {
293             Log.d(TAG, "  Activities: " + (r == null ? "<NONE>" : r));
294         }
295     }
296 
297     @GuardedBy("mLock")
addProvidersLocked(@onNull Computer computer, AndroidPackage pkg, boolean chatty)298     private void addProvidersLocked(@NonNull Computer computer, AndroidPackage pkg, boolean chatty) {
299         final int providersSize = ArrayUtils.size(pkg.getProviders());
300         StringBuilder r = null;
301         for (int i = 0; i < providersSize; i++) {
302             ParsedProvider p = pkg.getProviders().get(i);
303             mProviders.addProvider(computer, p);
304             if (p.getAuthority() != null) {
305                 String[] names = p.getAuthority().split(";");
306 
307                 // TODO(b/135203078): Remove this mutation
308                 ComponentMutateUtils.setAuthority(p, null);
309                 for (int j = 0; j < names.length; j++) {
310                     if (j == 1 && p.isSyncable()) {
311                         // We only want the first authority for a provider to possibly be
312                         // syncable, so if we already added this provider using a different
313                         // authority clear the syncable flag. We copy the provider before
314                         // changing it because the mProviders object contains a reference
315                         // to a provider that we don't want to change.
316                         // Only do this for the second authority since the resulting provider
317                         // object can be the same for all future authorities for this provider.
318                         p = new ParsedProviderImpl(p);
319                         ComponentMutateUtils.setSyncable(p, false);
320                     }
321                     if (!mProvidersByAuthority.containsKey(names[j])) {
322                         mProvidersByAuthority.put(names[j], p);
323                         if (p.getAuthority() == null) {
324                             ComponentMutateUtils.setAuthority(p, names[j]);
325                         } else {
326                             ComponentMutateUtils.setAuthority(p, p.getAuthority() + ";" + names[j]);
327                         }
328                         if (DEBUG_PACKAGE_SCANNING && chatty) {
329                             Log.d(TAG, "Registered content provider: " + names[j]
330                                     + ", className = " + p.getName()
331                                     + ", isSyncable = " + p.isSyncable());
332                         }
333                     } else {
334                         final ParsedProvider other =
335                                 mProvidersByAuthority.get(names[j]);
336                         final ComponentName component =
337                                 (other != null && other.getComponentName() != null)
338                                         ? other.getComponentName() : null;
339                         final String packageName =
340                                 component != null ? component.getPackageName() : "?";
341                         Slog.w(TAG, "Skipping provider name " + names[j]
342                                 + " (in package " + pkg.getPackageName() + ")"
343                                 + ": name already used by " + packageName);
344                     }
345                 }
346             }
347             if (DEBUG_PACKAGE_SCANNING && chatty) {
348                 if (r == null) {
349                     r = new StringBuilder(256);
350                 } else {
351                     r.append(' ');
352                 }
353                 r.append(p.getName());
354             }
355         }
356         if (DEBUG_PACKAGE_SCANNING && chatty) {
357             Log.d(TAG, "  Providers: " + (r == null ? "<NONE>" : r));
358         }
359     }
360 
361     @GuardedBy("mLock")
addReceiversLocked(@onNull Computer computer, AndroidPackage pkg, boolean chatty)362     private void addReceiversLocked(@NonNull Computer computer, AndroidPackage pkg, boolean chatty) {
363         final int receiversSize = ArrayUtils.size(pkg.getReceivers());
364         StringBuilder r = null;
365         for (int i = 0; i < receiversSize; i++) {
366             ParsedActivity a = pkg.getReceivers().get(i);
367             mReceivers.addActivity(computer, a, "receiver", null);
368             if (DEBUG_PACKAGE_SCANNING && chatty) {
369                 if (r == null) {
370                     r = new StringBuilder(256);
371                 } else {
372                     r.append(' ');
373                 }
374                 r.append(a.getName());
375             }
376         }
377         if (DEBUG_PACKAGE_SCANNING && chatty) {
378             Log.d(TAG, "  Receivers: " + (r == null ? "<NONE>" : r));
379         }
380     }
381 
382     @GuardedBy("mLock")
addServicesLocked(@onNull Computer computer, AndroidPackage pkg, boolean chatty)383     private void addServicesLocked(@NonNull Computer computer, AndroidPackage pkg, boolean chatty) {
384         final int servicesSize = ArrayUtils.size(pkg.getServices());
385         StringBuilder r = null;
386         for (int i = 0; i < servicesSize; i++) {
387             ParsedService s = pkg.getServices().get(i);
388             mServices.addService(computer, s);
389             if (DEBUG_PACKAGE_SCANNING && chatty) {
390                 if (r == null) {
391                     r = new StringBuilder(256);
392                 } else {
393                     r.append(' ');
394                 }
395                 r.append(s.getName());
396             }
397         }
398         if (DEBUG_PACKAGE_SCANNING && chatty) {
399             Log.d(TAG, "  Services: " + (r == null ? "<NONE>" : r));
400         }
401     }
402 
403     /**
404      * <em>WARNING</em> for performance reasons, the passed in intentList WILL BE
405      * MODIFIED. Do not pass in a list that should not be changed.
406      */
getIntentListSubset(List<ParsedIntentInfo> intentList, Function<IntentFilter, Iterator<T>> generator, Iterator<T> searchIterator)407     private static <T> void getIntentListSubset(List<ParsedIntentInfo> intentList,
408             Function<IntentFilter, Iterator<T>> generator, Iterator<T> searchIterator) {
409         // loop through the set of actions; every one must be found in the intent filter
410         while (searchIterator.hasNext()) {
411             // we must have at least one filter in the list to consider a match
412             if (intentList.size() == 0) {
413                 break;
414             }
415 
416             final T searchAction = searchIterator.next();
417 
418             // loop through the set of intent filters
419             final Iterator<ParsedIntentInfo> intentIter = intentList.iterator();
420             while (intentIter.hasNext()) {
421                 final ParsedIntentInfo intentInfo = intentIter.next();
422                 boolean selectionFound = false;
423 
424                 // loop through the intent filter's selection criteria; at least one
425                 // of them must match the searched criteria
426                 final Iterator<T> intentSelectionIter =
427                         generator.apply(intentInfo.getIntentFilter());
428                 while (intentSelectionIter != null && intentSelectionIter.hasNext()) {
429                     final T intentSelection = intentSelectionIter.next();
430                     if (intentSelection != null && intentSelection.equals(searchAction)) {
431                         selectionFound = true;
432                         break;
433                     }
434                 }
435 
436                 // the selection criteria wasn't found in this filter's set; this filter
437                 // is not a potential match
438                 if (!selectionFound) {
439                     intentIter.remove();
440                 }
441             }
442         }
443     }
444 
isProtectedAction(IntentFilter filter)445     private static boolean isProtectedAction(IntentFilter filter) {
446         final Iterator<String> actionsIter = filter.actionsIterator();
447         while (actionsIter != null && actionsIter.hasNext()) {
448             final String filterAction = actionsIter.next();
449             if (PROTECTED_ACTIONS.contains(filterAction)) {
450                 return true;
451             }
452         }
453         return false;
454     }
455 
456     /**
457      * Finds a privileged activity that matches the specified activity names.
458      */
findMatchingActivity( List<ParsedActivity> activityList, ParsedActivity activityInfo)459     private static ParsedActivity findMatchingActivity(
460             List<ParsedActivity> activityList, ParsedActivity activityInfo) {
461         for (ParsedActivity sysActivity : activityList) {
462             if (sysActivity.getName().equals(activityInfo.getName())) {
463                 return sysActivity;
464             }
465             if (sysActivity.getName().equals(activityInfo.getTargetActivity())) {
466                 return sysActivity;
467             }
468             if (sysActivity.getTargetActivity() != null) {
469                 if (sysActivity.getTargetActivity().equals(activityInfo.getName())) {
470                     return sysActivity;
471                 }
472                 if (sysActivity.getTargetActivity().equals(activityInfo.getTargetActivity())) {
473                     return sysActivity;
474                 }
475             }
476         }
477         return null;
478     }
479 
480     /**
481      * Adjusts the priority of the given intent filter according to policy.
482      * <p>
483      * <ul>
484      * <li>The priority for non privileged applications is capped to '0'</li>
485      * <li>The priority for protected actions on privileged applications is capped to '0'</li>
486      * <li>The priority for unbundled updates to privileged applications is capped to the
487      *      priority defined on the system partition</li>
488      * </ul>
489      * <p>
490      * <em>NOTE:</em> There is one exception. For security reasons, the setup wizard is
491      * allowed to obtain any priority on any action.
492      */
adjustPriority(@onNull Computer computer, List<ParsedActivity> systemActivities, ParsedActivity activity, ParsedIntentInfo intentInfo, String setupWizardPackage)493     private void adjustPriority(@NonNull Computer computer, List<ParsedActivity> systemActivities,
494             ParsedActivity activity, ParsedIntentInfo intentInfo, String setupWizardPackage) {
495         // nothing to do; priority is fine as-is
496         IntentFilter intentFilter = intentInfo.getIntentFilter();
497         if (intentFilter.getPriority() <= 0) {
498             return;
499         }
500 
501         String packageName = activity.getPackageName();
502         var packageState = computer.getPackageStateInternal(packageName);
503 
504         final boolean privilegedApp = packageState.isPrivileged();
505         String className = activity.getClassName();
506         if (!privilegedApp) {
507             // non-privileged applications can never define a priority >0
508             if (DEBUG_FILTERS) {
509                 Slog.i(TAG, "Non-privileged app; cap priority to 0;"
510                         + " package: " + packageName
511                         + " activity: " + className
512                         + " origPrio: " + intentFilter.getPriority());
513             }
514             intentFilter.setPriority(0);
515             return;
516         }
517 
518         if (isProtectedAction(intentFilter)) {
519             if (mDeferProtectedFilters) {
520                 // We can't deal with these just yet. No component should ever obtain a
521                 // >0 priority for a protected actions, with ONE exception -- the setup
522                 // wizard. The setup wizard, however, cannot be known until we're able to
523                 // query it for the category CATEGORY_SETUP_WIZARD. Which we can't do
524                 // until all intent filters have been processed. Chicken, meet egg.
525                 // Let the filter temporarily have a high priority and rectify the
526                 // priorities after all system packages have been scanned.
527                 if (mProtectedFilters == null) {
528                     mProtectedFilters = new ArrayList<>();
529                 }
530                 mProtectedFilters.add(Pair.create(activity, intentInfo));
531                 if (DEBUG_FILTERS) {
532                     Slog.i(TAG, "Protected action; save for later;"
533                             + " package: " + packageName
534                             + " activity: " + className
535                             + " origPrio: " + intentFilter.getPriority());
536                 }
537             } else {
538                 if (DEBUG_FILTERS && setupWizardPackage == null) {
539                     Slog.i(TAG, "No setup wizard;"
540                             + " All protected intents capped to priority 0");
541                 }
542                 if (packageName.equals(setupWizardPackage)) {
543                     if (DEBUG_FILTERS) {
544                         Slog.i(TAG, "Found setup wizard;"
545                                 + " allow priority " + intentFilter.getPriority() + ";"
546                                 + " package: " + packageName
547                                 + " activity: " + className
548                                 + " priority: " + intentFilter.getPriority());
549                     }
550                     // setup wizard gets whatever it wants
551                     return;
552                 }
553                 if (DEBUG_FILTERS) {
554                     Slog.i(TAG, "Protected action; cap priority to 0;"
555                             + " package: " + packageName
556                             + " activity: " + className
557                             + " origPrio: " + intentFilter.getPriority());
558                 }
559                 intentFilter.setPriority(0);
560             }
561             return;
562         }
563 
564         if (systemActivities == null) {
565             // the system package is not disabled; we're parsing the system partition
566 
567             // privileged apps on the system image get whatever priority they request
568             return;
569         }
570 
571         // privileged app unbundled update ... try to find the same activity
572 
573         ParsedActivity foundActivity = findMatchingActivity(systemActivities, activity);
574         if (foundActivity == null) {
575             // this is a new activity; it cannot obtain >0 priority
576             if (DEBUG_FILTERS) {
577                 Slog.i(TAG, "New activity; cap priority to 0;"
578                         + " package: " + packageName
579                         + " activity: " + className
580                         + " origPrio: " + intentFilter.getPriority());
581             }
582             intentFilter.setPriority(0);
583             return;
584         }
585 
586         // found activity, now check for filter equivalence
587 
588         // a shallow copy is enough; we modify the list, not its contents
589         final List<ParsedIntentInfo> intentListCopy =
590                 new ArrayList<>(foundActivity.getIntents());
591 
592         // find matching action subsets
593         final Iterator<String> actionsIterator = intentFilter.actionsIterator();
594         if (actionsIterator != null) {
595             getIntentListSubset(intentListCopy, IntentFilter::actionsIterator, actionsIterator);
596             if (intentListCopy.size() == 0) {
597                 // no more intents to match; we're not equivalent
598                 if (DEBUG_FILTERS) {
599                     Slog.i(TAG, "Mismatched action; cap priority to 0;"
600                             + " package: " + packageName
601                             + " activity: " + className
602                             + " origPrio: " + intentFilter.getPriority());
603                 }
604                 intentFilter.setPriority(0);
605                 return;
606             }
607         }
608 
609         // find matching category subsets
610         final Iterator<String> categoriesIterator = intentFilter.categoriesIterator();
611         if (categoriesIterator != null) {
612             getIntentListSubset(intentListCopy, IntentFilter::categoriesIterator,
613                     categoriesIterator);
614             if (intentListCopy.size() == 0) {
615                 // no more intents to match; we're not equivalent
616                 if (DEBUG_FILTERS) {
617                     Slog.i(TAG, "Mismatched category; cap priority to 0;"
618                             + " package: " + packageName
619                             + " activity: " + className
620                             + " origPrio: " + intentFilter.getPriority());
621                 }
622                 intentFilter.setPriority(0);
623                 return;
624             }
625         }
626 
627         // find matching schemes subsets
628         final Iterator<String> schemesIterator = intentFilter.schemesIterator();
629         if (schemesIterator != null) {
630             getIntentListSubset(intentListCopy, IntentFilter::schemesIterator, schemesIterator);
631             if (intentListCopy.size() == 0) {
632                 // no more intents to match; we're not equivalent
633                 if (DEBUG_FILTERS) {
634                     Slog.i(TAG, "Mismatched scheme; cap priority to 0;"
635                             + " package: " + packageName
636                             + " activity: " + className
637                             + " origPrio: " + intentFilter.getPriority());
638                 }
639                 intentFilter.setPriority(0);
640                 return;
641             }
642         }
643 
644         // find matching authorities subsets
645         final Iterator<IntentFilter.AuthorityEntry> authoritiesIterator =
646                 intentFilter.authoritiesIterator();
647         if (authoritiesIterator != null) {
648             getIntentListSubset(intentListCopy, IntentFilter::authoritiesIterator,
649                     authoritiesIterator);
650             if (intentListCopy.size() == 0) {
651                 // no more intents to match; we're not equivalent
652                 if (DEBUG_FILTERS) {
653                     Slog.i(TAG, "Mismatched authority; cap priority to 0;"
654                             + " package: " + packageName
655                             + " activity: " + className
656                             + " origPrio: " + intentFilter.getPriority());
657                 }
658                 intentFilter.setPriority(0);
659                 return;
660             }
661         }
662 
663         // we found matching filter(s); app gets the max priority of all intents
664         int cappedPriority = 0;
665         for (int i = intentListCopy.size() - 1; i >= 0; --i) {
666             cappedPriority = Math.max(cappedPriority,
667                     intentListCopy.get(i).getIntentFilter().getPriority());
668         }
669         if (intentFilter.getPriority() > cappedPriority) {
670             if (DEBUG_FILTERS) {
671                 Slog.i(TAG, "Found matching filter(s);"
672                         + " cap priority to " + cappedPriority + ";"
673                         + " package: " + packageName
674                         + " activity: " + className
675                         + " origPrio: " + intentFilter.getPriority());
676             }
677             intentFilter.setPriority(cappedPriority);
678             return;
679         }
680         // all this for nothing; the requested priority was <= what was on the system
681     }
682 
683     @GuardedBy("mLock")
removeAllComponentsLocked(AndroidPackage pkg, boolean chatty)684     private void removeAllComponentsLocked(AndroidPackage pkg, boolean chatty) {
685         int componentSize;
686         StringBuilder r;
687         int i;
688 
689         componentSize = ArrayUtils.size(pkg.getActivities());
690         r = null;
691         for (i = 0; i < componentSize; i++) {
692             ParsedActivity a = pkg.getActivities().get(i);
693             mActivities.removeActivity(a, "activity");
694             if (DEBUG_REMOVE && chatty) {
695                 if (r == null) {
696                     r = new StringBuilder(256);
697                 } else {
698                     r.append(' ');
699                 }
700                 r.append(a.getName());
701             }
702         }
703         if (DEBUG_REMOVE && chatty) {
704             Log.d(TAG, "  Activities: " + (r == null ? "<NONE>" : r));
705         }
706 
707         componentSize = ArrayUtils.size(pkg.getProviders());
708         r = null;
709         for (i = 0; i < componentSize; i++) {
710             ParsedProvider p = pkg.getProviders().get(i);
711             mProviders.removeProvider(p);
712             if (p.getAuthority() == null) {
713                 // Another content provider with this authority existed when this app was
714                 // installed, so this authority is null. Ignore it as we don't have to
715                 // unregister the provider.
716                 continue;
717             }
718             String[] names = p.getAuthority().split(";");
719             for (int j = 0; j < names.length; j++) {
720                 if (mProvidersByAuthority.get(names[j]) == p) {
721                     mProvidersByAuthority.remove(names[j]);
722                     if (DEBUG_REMOVE && chatty) {
723                         Log.d(TAG, "Unregistered content provider: " + names[j]
724                                 + ", className = " + p.getName() + ", isSyncable = "
725                                 + p.isSyncable());
726                     }
727                 }
728             }
729             if (DEBUG_REMOVE && chatty) {
730                 if (r == null) {
731                     r = new StringBuilder(256);
732                 } else {
733                     r.append(' ');
734                 }
735                 r.append(p.getName());
736             }
737         }
738         if (DEBUG_REMOVE && chatty) {
739             Log.d(TAG, "  Providers: " + (r == null ? "<NONE>" : r));
740         }
741 
742         componentSize = ArrayUtils.size(pkg.getReceivers());
743         r = null;
744         for (i = 0; i < componentSize; i++) {
745             ParsedActivity a = pkg.getReceivers().get(i);
746             mReceivers.removeActivity(a, "receiver");
747             if (DEBUG_REMOVE && chatty) {
748                 if (r == null) {
749                     r = new StringBuilder(256);
750                 } else {
751                     r.append(' ');
752                 }
753                 r.append(a.getName());
754             }
755         }
756         if (DEBUG_REMOVE && chatty) {
757             Log.d(TAG, "  Receivers: " + (r == null ? "<NONE>" : r));
758         }
759 
760         componentSize = ArrayUtils.size(pkg.getServices());
761         r = null;
762         for (i = 0; i < componentSize; i++) {
763             ParsedService s = pkg.getServices().get(i);
764             mServices.removeService(s);
765             if (DEBUG_REMOVE && chatty) {
766                 if (r == null) {
767                     r = new StringBuilder(256);
768                 } else {
769                     r.append(' ');
770                 }
771                 r.append(s.getName());
772             }
773         }
774         if (DEBUG_REMOVE && chatty) {
775             Log.d(TAG, "  Services: " + (r == null ? "<NONE>" : r));
776         }
777     }
778 
779     /** Asserts none of the providers defined in the given package haven't already been defined. */
assertProvidersNotDefined(@onNull AndroidPackage pkg)780     public void assertProvidersNotDefined(@NonNull AndroidPackage pkg)
781             throws PackageManagerException {
782         synchronized (mLock) {
783             final int providersSize = ArrayUtils.size(pkg.getProviders());
784             int i;
785             for (i = 0; i < providersSize; i++) {
786                 ParsedProvider p = pkg.getProviders().get(i);
787                 if (p.getAuthority() != null) {
788                     final String[] names = p.getAuthority().split(";");
789                     for (int j = 0; j < names.length; j++) {
790                         if (mProvidersByAuthority.containsKey(names[j])) {
791                             final ParsedProvider other = mProvidersByAuthority.get(names[j]);
792                             final String otherPackageName =
793                                     (other != null && other.getComponentName() != null)
794                                             ? other.getComponentName().getPackageName() : "?";
795                             // if installing over the same already-installed package,this is ok
796                             if (!otherPackageName.equals(pkg.getPackageName())) {
797                                 throw new PackageManagerException(
798                                         INSTALL_FAILED_CONFLICTING_PROVIDER,
799                                         "Can't install because provider name " + names[j]
800                                                 + " (in package " + pkg.getPackageName()
801                                                 + ") is already used by " + otherPackageName);
802                             }
803                         }
804                     }
805                 }
806             }
807         }
808     }
809 
810     private abstract static class MimeGroupsAwareIntentResolver<F extends Pair<?
811             extends ParsedComponent, ParsedIntentInfo>, R>
812             extends IntentResolver<F, R> {
813         private final ArrayMap<String, F[]> mMimeGroupToFilter = new ArrayMap<>();
814         private boolean mIsUpdatingMimeGroup = false;
815 
816         @NonNull
817         protected final UserManagerService mUserManager;
818 
819         // Default constructor
MimeGroupsAwareIntentResolver(@onNull UserManagerService userManager)820         MimeGroupsAwareIntentResolver(@NonNull UserManagerService userManager) {
821             mUserManager = userManager;
822         }
823 
824         // Copy constructor used in creating snapshots
MimeGroupsAwareIntentResolver(MimeGroupsAwareIntentResolver<F, R> orig, @NonNull UserManagerService userManager)825         MimeGroupsAwareIntentResolver(MimeGroupsAwareIntentResolver<F, R> orig,
826                 @NonNull UserManagerService userManager) {
827             mUserManager = userManager;
828             copyFrom(orig);
829             copyInto(mMimeGroupToFilter, orig.mMimeGroupToFilter);
830             mIsUpdatingMimeGroup = orig.mIsUpdatingMimeGroup;
831         }
832 
833         @Override
addFilter(@ullable PackageDataSnapshot snapshot, F f)834         public void addFilter(@Nullable PackageDataSnapshot snapshot, F f) {
835             IntentFilter intentFilter = getIntentFilter(f);
836             // We assume Computer is available for this class and all subclasses. Because this class
837             // uses subclass method override to handle logic, the Computer parameter must be in the
838             // base, leading to this odd nullability.
839             applyMimeGroups((Computer) snapshot, f);
840             super.addFilter(snapshot, f);
841 
842             if (!mIsUpdatingMimeGroup) {
843                 register_intent_filter(f, intentFilter.mimeGroupsIterator(), mMimeGroupToFilter,
844                         "      MimeGroup: ");
845             }
846         }
847 
848         @Override
removeFilterInternal(F f)849         protected void removeFilterInternal(F f) {
850             IntentFilter intentFilter = getIntentFilter(f);
851             if (!mIsUpdatingMimeGroup) {
852                 unregister_intent_filter(f, intentFilter.mimeGroupsIterator(), mMimeGroupToFilter,
853                         "      MimeGroup: ");
854             }
855 
856             super.removeFilterInternal(f);
857             intentFilter.clearDynamicDataTypes();
858         }
859 
860         /**
861          * Updates MIME group by applying changes to all IntentFilters
862          * that contain the group and repopulating m*ToFilter maps accordingly
863          *
864          * @param packageName package to which MIME group belongs
865          * @param mimeGroup MIME group to update
866          * @return true, if any intent filters were changed due to this update
867          */
updateMimeGroup(@onNull Computer computer, String packageName, String mimeGroup)868         public boolean updateMimeGroup(@NonNull Computer computer, String packageName,
869                 String mimeGroup) {
870             F[] filters = mMimeGroupToFilter.get(mimeGroup);
871             int n = filters != null ? filters.length : 0;
872 
873             mIsUpdatingMimeGroup = true;
874             boolean hasChanges = false;
875             F filter;
876             for (int i = 0; i < n && (filter = filters[i]) != null; i++) {
877                 if (isPackageForFilter(packageName, filter)) {
878                     hasChanges |= updateFilter(computer, filter);
879                 }
880             }
881             mIsUpdatingMimeGroup = false;
882             return hasChanges;
883         }
884 
updateFilter(@onNull Computer computer, F f)885         private boolean updateFilter(@NonNull Computer computer, F f) {
886             IntentFilter filter = getIntentFilter(f);
887             List<String> oldTypes = filter.dataTypes();
888             removeFilter(f);
889             addFilter(computer, f);
890             List<String> newTypes = filter.dataTypes();
891             return !equalLists(oldTypes, newTypes);
892         }
893 
equalLists(List<String> first, List<String> second)894         private boolean equalLists(List<String> first, List<String> second) {
895             if (first == null) {
896                 return second == null;
897             } else if (second == null) {
898                 return false;
899             }
900 
901             if (first.size() != second.size()) {
902                 return false;
903             }
904 
905             Collections.sort(first);
906             Collections.sort(second);
907             return first.equals(second);
908         }
909 
applyMimeGroups(@onNull Computer computer, F f)910         private void applyMimeGroups(@NonNull Computer computer, F f) {
911             IntentFilter filter = getIntentFilter(f);
912 
913             for (int i = filter.countMimeGroups() - 1; i >= 0; i--) {
914                 final PackageStateInternal packageState = computer.getPackageStateInternal(
915                         f.first.getPackageName());
916 
917                 Collection<String> mimeTypes = packageState == null
918                         ? Collections.emptyList() : packageState.getMimeGroups()
919                         .get(filter.getMimeGroup(i));
920 
921                 for (String mimeType : mimeTypes) {
922                     try {
923                         filter.addDynamicDataType(mimeType);
924                     } catch (IntentFilter.MalformedMimeTypeException e) {
925                         if (DEBUG) {
926                             Slog.w(TAG, "Malformed mime type: " + mimeType, e);
927                         }
928                     }
929                 }
930             }
931         }
932 
933         @Override
isFilterStopped(@onNull Computer computer, F filter, @UserIdInt int userId)934         protected boolean isFilterStopped(@NonNull Computer computer, F filter,
935                 @UserIdInt int userId) {
936             if (!mUserManager.exists(userId)) {
937                 return true;
938             }
939 
940             final PackageStateInternal packageState = computer.getPackageStateInternal(
941                     filter.first.getPackageName());
942             if (packageState == null || packageState.getPkg() == null) {
943                 return false;
944             }
945 
946             if (packageState.isSystem()) {
947                 // A system app can be considered in the stopped state only if it was originally
948                 // scanned in the stopped state.
949                 return packageState.isScannedAsStoppedSystemApp() &&
950                     packageState.getUserStateOrDefault(userId).isStopped();
951             }
952             return packageState.getUserStateOrDefault(userId).isStopped();
953         }
954     }
955 
956     public static class ActivityIntentResolver
957             extends MimeGroupsAwareIntentResolver<Pair<ParsedActivity, ParsedIntentInfo>, ResolveInfo> {
958 
959         @NonNull
960         private final UserNeedsBadgingCache mUserNeedsBadging;
961 
962         // Default constructor
ActivityIntentResolver(@onNull UserManagerService userManager, @NonNull UserNeedsBadgingCache userNeedsBadgingCache)963         ActivityIntentResolver(@NonNull UserManagerService userManager,
964                 @NonNull UserNeedsBadgingCache userNeedsBadgingCache) {
965             super(userManager);
966             mUserNeedsBadging = userNeedsBadgingCache;
967         }
968 
969         // Copy constructor used in creating snapshots
ActivityIntentResolver(@onNull ActivityIntentResolver orig, @NonNull UserManagerService userManager, @NonNull UserNeedsBadgingCache userNeedsBadgingCache)970         ActivityIntentResolver(@NonNull ActivityIntentResolver orig,
971                 @NonNull UserManagerService userManager,
972                 @NonNull UserNeedsBadgingCache userNeedsBadgingCache) {
973             super(orig, userManager);
974             mActivities.putAll(orig.mActivities);
975             mUserNeedsBadging = userNeedsBadgingCache;
976         }
977 
978         @Override
queryIntent(@onNull PackageDataSnapshot snapshot, Intent intent, String resolvedType, boolean defaultOnly, @UserIdInt int userId)979         public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
980                 String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
981             if (!mUserManager.exists(userId)) return null;
982             long flags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0);
983             return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, flags);
984         }
985 
queryIntent(@onNull Computer computer, Intent intent, String resolvedType, long flags, int userId)986         List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
987                 String resolvedType, long flags, int userId) {
988             if (!mUserManager.exists(userId)) {
989                 return null;
990             }
991             return super.queryIntent(computer, intent, resolvedType,
992                     (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId, flags);
993         }
994 
queryIntentForPackage(@onNull Computer computer, Intent intent, String resolvedType, long flags, List<ParsedActivity> packageActivities, int userId)995         List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
996                 String resolvedType, long flags, List<ParsedActivity> packageActivities,
997                 int userId) {
998             if (!mUserManager.exists(userId)) {
999                 return null;
1000             }
1001             if (packageActivities == null) {
1002                 return Collections.emptyList();
1003             }
1004             final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
1005             final int activitiesSize = packageActivities.size();
1006             ArrayList<Pair<ParsedActivity, ParsedIntentInfo>[]> listCut =
1007                     new ArrayList<>(activitiesSize);
1008 
1009             List<ParsedIntentInfo> intentFilters;
1010             for (int i = 0; i < activitiesSize; ++i) {
1011                 ParsedActivity activity = packageActivities.get(i);
1012                 intentFilters = activity.getIntents();
1013                 if (!intentFilters.isEmpty()) {
1014                     Pair<ParsedActivity, ParsedIntentInfo>[] array = newArray(intentFilters.size());
1015                     for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
1016                         array[arrayIndex] = Pair.create(activity, intentFilters.get(arrayIndex));
1017                     }
1018                     listCut.add(array);
1019                 }
1020             }
1021             return super.queryIntentFromList(computer, intent, resolvedType,
1022                     defaultOnly, listCut, userId, flags);
1023         }
1024 
addActivity(@onNull Computer computer, ParsedActivity a, String type, List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents)1025         protected void addActivity(@NonNull Computer computer, ParsedActivity a, String type,
1026                 List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents) {
1027             mActivities.put(a.getComponentName(), a);
1028             if (DEBUG_SHOW_INFO) {
1029                 Log.v(TAG, "  " + type + ":");
1030                 Log.v(TAG, "    Class=" + a.getName());
1031             }
1032             final int intentsSize = a.getIntents().size();
1033             for (int j = 0; j < intentsSize; j++) {
1034                 ParsedIntentInfo intent = a.getIntents().get(j);
1035                 IntentFilter intentFilter = intent.getIntentFilter();
1036                 if (newIntents != null && "activity".equals(type)) {
1037                     newIntents.add(Pair.create(a, intent));
1038                 }
1039                 if (DEBUG_SHOW_INFO) {
1040                     Log.v(TAG, "    IntentFilter:");
1041                     intentFilter.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
1042                 }
1043                 if (!intentFilter.debugCheck()) {
1044                     Log.w(TAG, "==> For Activity " + a.getName());
1045                 }
1046                 addFilter(computer, Pair.create(a, intent));
1047             }
1048         }
1049 
removeActivity(ParsedActivity a, String type)1050         protected void removeActivity(ParsedActivity a, String type) {
1051             mActivities.remove(a.getComponentName());
1052             if (DEBUG_SHOW_INFO) {
1053                 Log.v(TAG, "  " + type + ":");
1054                 Log.v(TAG, "    Class=" + a.getName());
1055             }
1056             final int intentsSize = a.getIntents().size();
1057             for (int j = 0; j < intentsSize; j++) {
1058                 ParsedIntentInfo intent = a.getIntents().get(j);
1059                 IntentFilter intentFilter = intent.getIntentFilter();
1060                 if (DEBUG_SHOW_INFO) {
1061                     Log.v(TAG, "    IntentFilter:");
1062                     intentFilter.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
1063                 }
1064                 removeFilter(Pair.create(a, intent));
1065             }
1066         }
1067 
1068         @Override
allowFilterResult(Pair<ParsedActivity, ParsedIntentInfo> filter, List<ResolveInfo> dest)1069         protected boolean allowFilterResult(Pair<ParsedActivity, ParsedIntentInfo> filter,
1070                 List<ResolveInfo> dest) {
1071             for (int i = dest.size() - 1; i >= 0; --i) {
1072                 ActivityInfo destAi = dest.get(i).activityInfo;
1073                 if (Objects.equals(destAi.name, filter.first.getName())
1074                         && Objects.equals(destAi.packageName, filter.first.getPackageName())) {
1075                     return false;
1076                 }
1077             }
1078             return true;
1079         }
1080 
1081         @Override
newArray(int size)1082         protected Pair<ParsedActivity, ParsedIntentInfo>[] newArray(int size) {
1083             //noinspection unchecked
1084             return (Pair<ParsedActivity, ParsedIntentInfo>[]) new Pair<?, ?>[size];
1085         }
1086 
1087         @Override
isPackageForFilter(String packageName, Pair<ParsedActivity, ParsedIntentInfo> info)1088         protected boolean isPackageForFilter(String packageName,
1089                 Pair<ParsedActivity, ParsedIntentInfo> info) {
1090             return packageName.equals(info.first.getPackageName());
1091         }
1092 
log(String reason, ParsedIntentInfo info, int match, int userId)1093         private void log(String reason, ParsedIntentInfo info, int match,
1094                 int userId) {
1095             Slog.w(TAG, reason
1096                     + "; match: "
1097                     + DebugUtils.flagsToString(IntentFilter.class, "MATCH_", match)
1098                     + "; userId: " + userId
1099                     + "; intent info: " + info);
1100         }
1101 
1102         @Override
newResult(@onNull Computer computer, Pair<ParsedActivity, ParsedIntentInfo> pair, int match, int userId, long customFlags)1103         protected ResolveInfo newResult(@NonNull Computer computer,
1104                 Pair<ParsedActivity, ParsedIntentInfo> pair, int match, int userId,
1105                 long customFlags) {
1106             ParsedActivity activity = pair.first;
1107             ParsedIntentInfo info = pair.second;
1108             IntentFilter intentFilter = info.getIntentFilter();
1109 
1110             if (!mUserManager.exists(userId)) {
1111                 if (DEBUG) {
1112                     log("User doesn't exist", info, match, userId);
1113                 }
1114                 return null;
1115             }
1116 
1117             final PackageStateInternal packageState =
1118                     computer.getPackageStateInternal(activity.getPackageName());
1119             if (packageState == null || packageState.getPkg() == null
1120                     || !PackageStateUtils.isEnabledAndMatches(packageState, activity, customFlags,
1121                     userId)) {
1122                 if (DEBUG) {
1123                     log("!PackageManagerInternal.isEnabledAndMatches; flags="
1124                             + DebugUtils.flagsToString(PackageManager.class, "MATCH_", customFlags),
1125                             info, match, userId);
1126                 }
1127                 return null;
1128             }
1129             final PackageUserStateInternal userState = packageState.getUserStateOrDefault(userId);
1130             ActivityInfo ai = PackageInfoUtils.generateActivityInfo(packageState.getPkg(), activity,
1131                     customFlags, userState, userId, packageState);
1132             if (ai == null) {
1133                 if (DEBUG) {
1134                     log("Failed to create ActivityInfo based on " + activity, info, match,
1135                             userId);
1136                 }
1137                 return null;
1138             }
1139             final boolean matchExplicitlyVisibleOnly =
1140                     (customFlags & PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY) != 0;
1141             final boolean matchVisibleToInstantApp =
1142                     (customFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
1143             final boolean componentVisible =
1144                     matchVisibleToInstantApp
1145                     && intentFilter.isVisibleToInstantApp()
1146                     && (!matchExplicitlyVisibleOnly
1147                             || intentFilter.isExplicitlyVisibleToInstantApp());
1148             final boolean matchInstantApp = (customFlags & PackageManager.MATCH_INSTANT) != 0;
1149             // throw out filters that aren't visible to ephemeral apps
1150             if (matchVisibleToInstantApp && !(componentVisible || userState.isInstantApp())) {
1151                 if (DEBUG) {
1152                     log("Filter(s) not visible to ephemeral apps"
1153                             + "; matchVisibleToInstantApp=" + matchVisibleToInstantApp
1154                             + "; matchInstantApp=" + matchInstantApp
1155                             + "; info.isVisibleToInstantApp()="
1156                                     + intentFilter.isVisibleToInstantApp()
1157                             + "; matchExplicitlyVisibleOnly=" + matchExplicitlyVisibleOnly
1158                             + "; info.isExplicitlyVisibleToInstantApp()="
1159                                     + intentFilter.isExplicitlyVisibleToInstantApp(),
1160                             info, match, userId);
1161                 }
1162                 return null;
1163             }
1164             // throw out instant app filters if we're not explicitly requesting them
1165             if (!matchInstantApp && userState.isInstantApp()) {
1166                 if (DEBUG) {
1167                     log("Instant app filter is not explicitly requested", info, match, userId);
1168                 }
1169                 return null;
1170             }
1171             // throw out instant app filters if updates are available; will trigger
1172             // instant app resolution
1173             if (userState.isInstantApp() && packageState.isUpdateAvailable()) {
1174                 if (DEBUG) {
1175                     log("Instant app update is available", info, match, userId);
1176                 }
1177                 return null;
1178             }
1179             final ResolveInfo res =
1180                     new ResolveInfo(intentFilter.hasCategory(Intent.CATEGORY_BROWSABLE));
1181             res.activityInfo = ai;
1182             if ((customFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
1183                 res.filter = intentFilter;
1184             }
1185             res.handleAllWebDataURI = intentFilter.handleAllWebDataURI();
1186             res.priority = intentFilter.getPriority();
1187             // TODO(b/135203078): This field was unwritten and does nothing
1188 //            res.preferredOrder = pkg.getPreferredOrder();
1189             //System.out.println("Result: " + res.activityInfo.className +
1190             //                   " = " + res.priority);
1191             res.match = match;
1192             res.isDefault = info.isHasDefault();
1193             res.labelRes = info.getLabelRes();
1194             res.nonLocalizedLabel = info.getNonLocalizedLabel();
1195             if (mUserNeedsBadging.get(userId)) {
1196                 res.noResourceId = true;
1197             } else {
1198                 res.icon = info.getIcon();
1199             }
1200             res.iconResourceId = info.getIcon();
1201             res.system = res.activityInfo.applicationInfo.isSystemApp();
1202             res.isInstantAppAvailable = userState.isInstantApp();
1203             res.userHandle = UserHandle.of(userId);
1204             return res;
1205         }
1206 
1207         @Override
sortResults(List<ResolveInfo> results)1208         protected void sortResults(List<ResolveInfo> results) {
1209             results.sort(RESOLVE_PRIORITY_SORTER);
1210         }
1211 
1212         @Override
dumpFilter(PrintWriter out, String prefix, Pair<ParsedActivity, ParsedIntentInfo> pair)1213         protected void dumpFilter(PrintWriter out, String prefix,
1214                 Pair<ParsedActivity, ParsedIntentInfo> pair) {
1215             ParsedActivity activity = pair.first;
1216             ParsedIntentInfo filter = pair.second;
1217 
1218             out.print(prefix);
1219             out.print(Integer.toHexString(System.identityHashCode(activity)));
1220             out.print(' ');
1221             ComponentName.printShortString(out, activity.getPackageName(),
1222                     activity.getClassName());
1223             out.print(" filter ");
1224             out.println(Integer.toHexString(System.identityHashCode(filter)));
1225         }
1226 
1227         @Override
filterToLabel(Pair<ParsedActivity, ParsedIntentInfo> filter)1228         protected Object filterToLabel(Pair<ParsedActivity, ParsedIntentInfo> filter) {
1229             return filter;
1230         }
1231 
dumpFilterLabel(PrintWriter out, String prefix, Object label, int count)1232         protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
1233             @SuppressWarnings("unchecked") Pair<ParsedActivity, ParsedIntentInfo> pair =
1234                     (Pair<ParsedActivity, ParsedIntentInfo>) label;
1235             out.print(prefix);
1236             out.print(Integer.toHexString(System.identityHashCode(pair.first)));
1237             out.print(' ');
1238             ComponentName.printShortString(out, pair.first.getPackageName(),
1239                     pair.first.getClassName());
1240             if (count > 1) {
1241                 out.print(" ("); out.print(count); out.print(" filters)");
1242             }
1243             out.println();
1244         }
1245 
1246         @Override
getIntentFilter( @onNull Pair<ParsedActivity, ParsedIntentInfo> input)1247         protected IntentFilter getIntentFilter(
1248                 @NonNull Pair<ParsedActivity, ParsedIntentInfo> input) {
1249             return input.second.getIntentFilter();
1250         }
1251 
getResolveList(AndroidPackage pkg)1252         protected List<ParsedActivity> getResolveList(AndroidPackage pkg) {
1253             return pkg.getActivities();
1254         }
1255 
1256         // Keys are String (activity class name), values are Activity.  This attribute is
1257         // protected because it is accessed directly from ComponentResolver.  That works
1258         // even if the attribute is private, but fails for subclasses of
1259         // ActivityIntentResolver.
1260         protected final ArrayMap<ComponentName, ParsedActivity> mActivities =
1261                 new ArrayMap<>();
1262     }
1263 
1264     // Both receivers and activities share a class, but point to different get methods
1265     public static final class ReceiverIntentResolver extends ActivityIntentResolver {
1266 
1267         // Default constructor
ReceiverIntentResolver(@onNull UserManagerService userManager, @NonNull UserNeedsBadgingCache userNeedsBadgingCache)1268         ReceiverIntentResolver(@NonNull UserManagerService userManager,
1269                 @NonNull UserNeedsBadgingCache userNeedsBadgingCache) {
1270             super(userManager, userNeedsBadgingCache);
1271         }
1272 
1273         // Copy constructor used in creating snapshots
ReceiverIntentResolver(@onNull ReceiverIntentResolver orig, @NonNull UserManagerService userManager, @NonNull UserNeedsBadgingCache userNeedsBadgingCache)1274         ReceiverIntentResolver(@NonNull ReceiverIntentResolver orig,
1275                 @NonNull UserManagerService userManager,
1276                 @NonNull UserNeedsBadgingCache userNeedsBadgingCache) {
1277             super(orig, userManager, userNeedsBadgingCache);
1278         }
1279 
1280         @Override
getResolveList(AndroidPackage pkg)1281         protected List<ParsedActivity> getResolveList(AndroidPackage pkg) {
1282             return pkg.getReceivers();
1283         }
1284     }
1285 
1286     public static final class ProviderIntentResolver
1287             extends MimeGroupsAwareIntentResolver<Pair<ParsedProvider, ParsedIntentInfo>, ResolveInfo> {
1288         // Default constructor
ProviderIntentResolver(@onNull UserManagerService userManager)1289         ProviderIntentResolver(@NonNull UserManagerService userManager) {
1290             super(userManager);
1291         }
1292 
1293         // Copy constructor used in creating snapshots
ProviderIntentResolver(@onNull ProviderIntentResolver orig, @NonNull UserManagerService userManager)1294         ProviderIntentResolver(@NonNull ProviderIntentResolver orig,
1295                 @NonNull UserManagerService userManager) {
1296             super(orig, userManager);
1297             mProviders.putAll(orig.mProviders);
1298         }
1299 
1300         @Override
queryIntent(@onNull PackageDataSnapshot snapshot, Intent intent, String resolvedType, boolean defaultOnly, @UserIdInt int userId)1301         public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
1302                 String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
1303             if (!mUserManager.exists(userId)) {
1304                 return null;
1305             }
1306             long flags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
1307             return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, flags);
1308         }
1309 
1310         @Nullable
queryIntent(@onNull Computer computer, Intent intent, String resolvedType, long flags, int userId)1311         List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
1312                 String resolvedType, long flags, int userId) {
1313             if (!mUserManager.exists(userId)) {
1314                 return null;
1315             }
1316             return super.queryIntent(computer, intent, resolvedType,
1317                     (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId, flags);
1318         }
1319 
1320         @Nullable
queryIntentForPackage(@onNull Computer computer, Intent intent, String resolvedType, long flags, List<ParsedProvider> packageProviders, int userId)1321         List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
1322                 String resolvedType, long flags, List<ParsedProvider> packageProviders,
1323                 int userId) {
1324             if (!mUserManager.exists(userId)) {
1325                 return null;
1326             }
1327             if (packageProviders == null) {
1328                 return Collections.emptyList();
1329             }
1330             final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
1331             final int providersSize = packageProviders.size();
1332             ArrayList<Pair<ParsedProvider, ParsedIntentInfo>[]> listCut =
1333                     new ArrayList<>(providersSize);
1334 
1335             List<ParsedIntentInfo> intentFilters;
1336             for (int i = 0; i < providersSize; ++i) {
1337                 ParsedProvider provider = packageProviders.get(i);
1338                 intentFilters = provider.getIntents();
1339                 if (!intentFilters.isEmpty()) {
1340                     Pair<ParsedProvider, ParsedIntentInfo>[] array = newArray(intentFilters.size());
1341                     for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
1342                         array[arrayIndex] = Pair.create(provider, intentFilters.get(arrayIndex));
1343                     }
1344                     listCut.add(array);
1345                 }
1346             }
1347             return super.queryIntentFromList(computer, intent, resolvedType,
1348                     defaultOnly, listCut, userId, flags);
1349         }
1350 
addProvider(@onNull Computer computer, ParsedProvider p)1351         void addProvider(@NonNull Computer computer, ParsedProvider p) {
1352             if (mProviders.containsKey(p.getComponentName())) {
1353                 Slog.w(TAG, "Provider " + p.getComponentName() + " already defined; ignoring");
1354                 return;
1355             }
1356 
1357             mProviders.put(p.getComponentName(), p);
1358             if (DEBUG_SHOW_INFO) {
1359                 Log.v(TAG, "  provider:");
1360                 Log.v(TAG, "    Class=" + p.getName());
1361             }
1362             final int intentsSize = p.getIntents().size();
1363             int j;
1364             for (j = 0; j < intentsSize; j++) {
1365                 ParsedIntentInfo intent = p.getIntents().get(j);
1366                 IntentFilter intentFilter = intent.getIntentFilter();
1367                 if (DEBUG_SHOW_INFO) {
1368                     Log.v(TAG, "    IntentFilter:");
1369                     intentFilter.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
1370                 }
1371                 if (!intentFilter.debugCheck()) {
1372                     Log.w(TAG, "==> For Provider " + p.getName());
1373                 }
1374                 addFilter(computer, Pair.create(p, intent));
1375             }
1376         }
1377 
removeProvider(ParsedProvider p)1378         void removeProvider(ParsedProvider p) {
1379             mProviders.remove(p.getComponentName());
1380             if (DEBUG_SHOW_INFO) {
1381                 Log.v(TAG, "  provider:");
1382                 Log.v(TAG, "    Class=" + p.getName());
1383             }
1384             final int intentsSize = p.getIntents().size();
1385             int j;
1386             for (j = 0; j < intentsSize; j++) {
1387                 ParsedIntentInfo intent = p.getIntents().get(j);
1388                 IntentFilter intentFilter = intent.getIntentFilter();
1389                 if (DEBUG_SHOW_INFO) {
1390                     Log.v(TAG, "    IntentFilter:");
1391                     intentFilter.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
1392                 }
1393                 removeFilter(Pair.create(p, intent));
1394             }
1395         }
1396 
1397         @Override
allowFilterResult(Pair<ParsedProvider, ParsedIntentInfo> filter, List<ResolveInfo> dest)1398         protected boolean allowFilterResult(Pair<ParsedProvider, ParsedIntentInfo> filter,
1399                 List<ResolveInfo> dest) {
1400             for (int i = dest.size() - 1; i >= 0; i--) {
1401                 ProviderInfo destPi = dest.get(i).providerInfo;
1402                 if (Objects.equals(destPi.name, filter.first.getClassName())
1403                         && Objects.equals(destPi.packageName, filter.first.getPackageName())) {
1404                     return false;
1405                 }
1406             }
1407             return true;
1408         }
1409 
1410         @Override
newArray(int size)1411         protected Pair<ParsedProvider, ParsedIntentInfo>[] newArray(int size) {
1412             //noinspection unchecked
1413             return (Pair<ParsedProvider, ParsedIntentInfo>[]) new Pair<?, ?>[size];
1414         }
1415 
1416         @Override
isPackageForFilter(String packageName, Pair<ParsedProvider, ParsedIntentInfo> info)1417         protected boolean isPackageForFilter(String packageName,
1418                 Pair<ParsedProvider, ParsedIntentInfo> info) {
1419             return packageName.equals(info.first.getPackageName());
1420         }
1421 
1422         @Override
newResult(@onNull Computer computer, Pair<ParsedProvider, ParsedIntentInfo> pair, int match, int userId, long customFlags)1423         protected ResolveInfo newResult(@NonNull Computer computer,
1424                 Pair<ParsedProvider, ParsedIntentInfo> pair, int match, int userId,
1425                 long customFlags) {
1426             if (!mUserManager.exists(userId)) {
1427                 return null;
1428             }
1429 
1430             ParsedProvider provider = pair.first;
1431             ParsedIntentInfo intentInfo = pair.second;
1432             IntentFilter filter = intentInfo.getIntentFilter();
1433 
1434             PackageStateInternal packageState =
1435                     computer.getPackageStateInternal(provider.getPackageName());
1436             if (packageState == null || packageState.getPkg() == null
1437                     || !PackageStateUtils.isEnabledAndMatches(packageState, provider, customFlags,
1438                     userId)) {
1439                 return null;
1440             }
1441 
1442             final PackageUserStateInternal userState = packageState.getUserStateOrDefault(userId);
1443             final boolean matchVisibleToInstantApp = (customFlags
1444                     & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
1445             final boolean isInstantApp = (customFlags & PackageManager.MATCH_INSTANT) != 0;
1446             // throw out filters that aren't visible to instant applications
1447             if (matchVisibleToInstantApp
1448                     && !(filter.isVisibleToInstantApp() || userState.isInstantApp())) {
1449                 return null;
1450             }
1451             // throw out instant application filters if we're not explicitly requesting them
1452             if (!isInstantApp && userState.isInstantApp()) {
1453                 return null;
1454             }
1455             // throw out instant application filters if updates are available; will trigger
1456             // instant application resolution
1457             if (userState.isInstantApp() && packageState.isUpdateAvailable()) {
1458                 return null;
1459             }
1460             final ApplicationInfo appInfo = PackageInfoUtils.generateApplicationInfo(
1461                     packageState.getPkg(), customFlags, userState, userId, packageState);
1462             if (appInfo == null) {
1463                 return null;
1464             }
1465             ProviderInfo pi = PackageInfoUtils.generateProviderInfo(packageState.getPkg(), provider,
1466                     customFlags, userState, appInfo, userId, packageState);
1467             if (pi == null) {
1468                 return null;
1469             }
1470             final ResolveInfo res = new ResolveInfo();
1471             res.providerInfo = pi;
1472             if ((customFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
1473                 res.filter = filter;
1474             }
1475             res.priority = filter.getPriority();
1476             // TODO(b/135203078): This field was unwritten and does nothing
1477 //            res.preferredOrder = pkg.getPreferredOrder();
1478             res.match = match;
1479             res.isDefault = intentInfo.isHasDefault();
1480             res.labelRes = intentInfo.getLabelRes();
1481             res.nonLocalizedLabel = intentInfo.getNonLocalizedLabel();
1482             res.icon = intentInfo.getIcon();
1483             res.system = res.providerInfo.applicationInfo.isSystemApp();
1484             return res;
1485         }
1486 
1487         @Override
sortResults(List<ResolveInfo> results)1488         protected void sortResults(List<ResolveInfo> results) {
1489             results.sort(RESOLVE_PRIORITY_SORTER);
1490         }
1491 
1492         @Override
dumpFilter(PrintWriter out, String prefix, Pair<ParsedProvider, ParsedIntentInfo> pair)1493         protected void dumpFilter(PrintWriter out, String prefix,
1494                 Pair<ParsedProvider, ParsedIntentInfo> pair) {
1495             ParsedProvider provider = pair.first;
1496             ParsedIntentInfo filter = pair.second;
1497 
1498             out.print(prefix);
1499             out.print(Integer.toHexString(System.identityHashCode(provider)));
1500             out.print(' ');
1501             ComponentName.printShortString(out, provider.getPackageName(), provider.getClassName());
1502             out.print(" filter ");
1503             out.println(Integer.toHexString(System.identityHashCode(filter)));
1504         }
1505 
1506         @Override
filterToLabel(Pair<ParsedProvider, ParsedIntentInfo> filter)1507         protected Object filterToLabel(Pair<ParsedProvider, ParsedIntentInfo> filter) {
1508             return filter;
1509         }
1510 
dumpFilterLabel(PrintWriter out, String prefix, Object label, int count)1511         protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
1512             @SuppressWarnings("unchecked") final Pair<ParsedProvider, ParsedIntentInfo> pair =
1513                     (Pair<ParsedProvider, ParsedIntentInfo>) label;
1514             out.print(prefix);
1515             out.print(Integer.toHexString(System.identityHashCode(pair.first)));
1516             out.print(' ');
1517             ComponentName.printShortString(out, pair.first.getPackageName(),
1518                     pair.first.getClassName());
1519             if (count > 1) {
1520                 out.print(" (");
1521                 out.print(count);
1522                 out.print(" filters)");
1523             }
1524             out.println();
1525         }
1526 
1527         @Override
getIntentFilter( @onNull Pair<ParsedProvider, ParsedIntentInfo> input)1528         protected IntentFilter getIntentFilter(
1529                 @NonNull Pair<ParsedProvider, ParsedIntentInfo> input) {
1530             return input.second.getIntentFilter();
1531         }
1532 
1533         final ArrayMap<ComponentName, ParsedProvider> mProviders = new ArrayMap<>();
1534     }
1535 
1536     public static final class ServiceIntentResolver
1537             extends MimeGroupsAwareIntentResolver<Pair<ParsedService, ParsedIntentInfo>, ResolveInfo> {
1538         // Default constructor
ServiceIntentResolver(@onNull UserManagerService userManager)1539         ServiceIntentResolver(@NonNull UserManagerService userManager) {
1540             super(userManager);
1541         }
1542 
1543         // Copy constructor used in creating snapshots
ServiceIntentResolver(@onNull ServiceIntentResolver orig, @NonNull UserManagerService userManager)1544         ServiceIntentResolver(@NonNull ServiceIntentResolver orig,
1545                 @NonNull UserManagerService userManager) {
1546             super(orig, userManager);
1547             mServices.putAll(orig.mServices);
1548         }
1549 
1550         @Override
queryIntent(@onNull PackageDataSnapshot snapshot, Intent intent, String resolvedType, boolean defaultOnly, @UserIdInt int userId)1551         public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
1552                 String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
1553             if (!mUserManager.exists(userId)) {
1554                 return null;
1555             }
1556             long flags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
1557             return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, flags);
1558         }
1559 
queryIntent(@onNull Computer computer, Intent intent, String resolvedType, long flags, int userId)1560         List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
1561                 String resolvedType, long flags, int userId) {
1562             if (!mUserManager.exists(userId)) return null;
1563             return super.queryIntent(computer, intent, resolvedType,
1564                     (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId, flags);
1565         }
1566 
queryIntentForPackage(@onNull Computer computer, Intent intent, String resolvedType, long flags, List<ParsedService> packageServices, int userId)1567         List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
1568                 String resolvedType, long flags, List<ParsedService> packageServices, int userId) {
1569             if (!mUserManager.exists(userId)) return null;
1570             if (packageServices == null) {
1571                 return Collections.emptyList();
1572             }
1573             final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
1574             final int servicesSize = packageServices.size();
1575             ArrayList<Pair<ParsedService, ParsedIntentInfo>[]> listCut =
1576                     new ArrayList<>(servicesSize);
1577 
1578             List<ParsedIntentInfo> intentFilters;
1579             for (int i = 0; i < servicesSize; ++i) {
1580                 ParsedService service = packageServices.get(i);
1581                 intentFilters = service.getIntents();
1582                 if (intentFilters.size() > 0) {
1583                     Pair<ParsedService, ParsedIntentInfo>[] array = newArray(intentFilters.size());
1584                     for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
1585                         array[arrayIndex] = Pair.create(service, intentFilters.get(arrayIndex));
1586                     }
1587                     listCut.add(array);
1588                 }
1589             }
1590             return super.queryIntentFromList(computer, intent, resolvedType,
1591                     defaultOnly, listCut, userId, flags);
1592         }
1593 
addService(@onNull Computer computer, ParsedService s)1594         void addService(@NonNull Computer computer, ParsedService s) {
1595             mServices.put(s.getComponentName(), s);
1596             if (DEBUG_SHOW_INFO) {
1597                 Log.v(TAG, "  service:");
1598                 Log.v(TAG, "    Class=" + s.getName());
1599             }
1600             final int intentsSize = s.getIntents().size();
1601             int j;
1602             for (j = 0; j < intentsSize; j++) {
1603                 ParsedIntentInfo intent = s.getIntents().get(j);
1604                 IntentFilter intentFilter = intent.getIntentFilter();
1605                 if (DEBUG_SHOW_INFO) {
1606                     Log.v(TAG, "    IntentFilter:");
1607                     intentFilter.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
1608                 }
1609                 if (!intentFilter.debugCheck()) {
1610                     Log.w(TAG, "==> For Service " + s.getName());
1611                 }
1612                 addFilter(computer, Pair.create(s, intent));
1613             }
1614         }
1615 
removeService(ParsedService s)1616         void removeService(ParsedService s) {
1617             mServices.remove(s.getComponentName());
1618             if (DEBUG_SHOW_INFO) {
1619                 Log.v(TAG, "  service:");
1620                 Log.v(TAG, "    Class=" + s.getName());
1621             }
1622             final int intentsSize = s.getIntents().size();
1623             int j;
1624             for (j = 0; j < intentsSize; j++) {
1625                 ParsedIntentInfo intent = s.getIntents().get(j);
1626                 IntentFilter intentFilter = intent.getIntentFilter();
1627                 if (DEBUG_SHOW_INFO) {
1628                     Log.v(TAG, "    IntentFilter:");
1629                     intentFilter.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
1630                 }
1631                 removeFilter(Pair.create(s, intent));
1632             }
1633         }
1634 
1635         @Override
allowFilterResult(Pair<ParsedService, ParsedIntentInfo> filter, List<ResolveInfo> dest)1636         protected boolean allowFilterResult(Pair<ParsedService, ParsedIntentInfo> filter,
1637                 List<ResolveInfo> dest) {
1638             for (int i = dest.size() - 1; i >= 0; --i) {
1639                 ServiceInfo destAi = dest.get(i).serviceInfo;
1640                 if (Objects.equals(destAi.name, filter.first.getClassName())
1641                         && Objects.equals(destAi.packageName, filter.first.getPackageName())) {
1642                     return false;
1643                 }
1644             }
1645             return true;
1646         }
1647 
1648         @Override
newArray(int size)1649         protected Pair<ParsedService, ParsedIntentInfo>[] newArray(int size) {
1650             //noinspection unchecked
1651             return (Pair<ParsedService, ParsedIntentInfo>[]) new Pair<?, ?>[size];
1652         }
1653 
1654         @Override
isPackageForFilter(String packageName, Pair<ParsedService, ParsedIntentInfo> info)1655         protected boolean isPackageForFilter(String packageName,
1656                 Pair<ParsedService, ParsedIntentInfo> info) {
1657             return packageName.equals(info.first.getPackageName());
1658         }
1659 
1660         @Override
newResult(@onNull Computer computer, Pair<ParsedService, ParsedIntentInfo> pair, int match, int userId, long customFlags)1661         protected ResolveInfo newResult(@NonNull Computer computer,
1662                 Pair<ParsedService, ParsedIntentInfo> pair, int match, int userId,
1663                 long customFlags) {
1664             if (!mUserManager.exists(userId)) return null;
1665 
1666             ParsedService service = pair.first;
1667             ParsedIntentInfo intentInfo = pair.second;
1668             IntentFilter filter = intentInfo.getIntentFilter();
1669 
1670             final PackageStateInternal packageState = computer.getPackageStateInternal(
1671                     service.getPackageName());
1672             if (packageState == null || packageState.getPkg() == null
1673                     || !PackageStateUtils.isEnabledAndMatches(packageState, service, customFlags,
1674                     userId)) {
1675                 return null;
1676             }
1677 
1678             final PackageUserStateInternal userState = packageState.getUserStateOrDefault(userId);
1679             ServiceInfo si = PackageInfoUtils.generateServiceInfo(packageState.getPkg(), service,
1680                     customFlags, userState, userId, packageState);
1681             if (si == null) {
1682                 return null;
1683             }
1684             final boolean matchVisibleToInstantApp =
1685                     (customFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
1686             final boolean isInstantApp = (customFlags & PackageManager.MATCH_INSTANT) != 0;
1687             // throw out filters that aren't visible to ephemeral apps
1688             if (matchVisibleToInstantApp
1689                     && !(filter.isVisibleToInstantApp() || userState.isInstantApp())) {
1690                 return null;
1691             }
1692             // throw out ephemeral filters if we're not explicitly requesting them
1693             if (!isInstantApp && userState.isInstantApp()) {
1694                 return null;
1695             }
1696             // throw out instant app filters if updates are available; will trigger
1697             // instant app resolution
1698             if (userState.isInstantApp() && packageState.isUpdateAvailable()) {
1699                 return null;
1700             }
1701             final ResolveInfo res = new ResolveInfo();
1702             res.serviceInfo = si;
1703             if ((customFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
1704                 res.filter = filter;
1705             }
1706             res.priority = filter.getPriority();
1707             // TODO(b/135203078): This field was unwritten and does nothing
1708 //            res.preferredOrder = pkg.getPreferredOrder();
1709             res.match = match;
1710             res.isDefault = intentInfo.isHasDefault();
1711             res.labelRes = intentInfo.getLabelRes();
1712             res.nonLocalizedLabel = intentInfo.getNonLocalizedLabel();
1713             res.icon = intentInfo.getIcon();
1714             res.system = res.serviceInfo.applicationInfo.isSystemApp();
1715             return res;
1716         }
1717 
1718         @Override
sortResults(List<ResolveInfo> results)1719         protected void sortResults(List<ResolveInfo> results) {
1720             results.sort(RESOLVE_PRIORITY_SORTER);
1721         }
1722 
1723         @Override
dumpFilter(PrintWriter out, String prefix, Pair<ParsedService, ParsedIntentInfo> pair)1724         protected void dumpFilter(PrintWriter out, String prefix,
1725                 Pair<ParsedService, ParsedIntentInfo> pair) {
1726             ParsedService service = pair.first;
1727             ParsedIntentInfo filter = pair.second;
1728 
1729             out.print(prefix);
1730             out.print(Integer.toHexString(System.identityHashCode(service)));
1731             out.print(' ');
1732             ComponentName.printShortString(out, service.getPackageName(), service.getClassName());
1733             out.print(" filter ");
1734             out.print(Integer.toHexString(System.identityHashCode(filter)));
1735             if (service.getPermission() != null) {
1736                 out.print(" permission "); out.println(service.getPermission());
1737             } else {
1738                 out.println();
1739             }
1740         }
1741 
1742         @Override
filterToLabel(Pair<ParsedService, ParsedIntentInfo> filter)1743         protected Object filterToLabel(Pair<ParsedService, ParsedIntentInfo> filter) {
1744             return filter;
1745         }
1746 
dumpFilterLabel(PrintWriter out, String prefix, Object label, int count)1747         protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
1748             @SuppressWarnings("unchecked") final Pair<ParsedService, ParsedIntentInfo> pair =
1749                     (Pair<ParsedService, ParsedIntentInfo>) label;
1750             out.print(prefix);
1751             out.print(Integer.toHexString(System.identityHashCode(pair.first)));
1752             out.print(' ');
1753             ComponentName.printShortString(out, pair.first.getPackageName(),
1754                     pair.first.getClassName());
1755             if (count > 1) {
1756                 out.print(" ("); out.print(count); out.print(" filters)");
1757             }
1758             out.println();
1759         }
1760 
1761         @Override
getIntentFilter( @onNull Pair<ParsedService, ParsedIntentInfo> input)1762         protected IntentFilter getIntentFilter(
1763                 @NonNull Pair<ParsedService, ParsedIntentInfo> input) {
1764             return input.second.getIntentFilter();
1765         }
1766 
1767         // Keys are String (activity class name), values are Activity.
1768         final ArrayMap<ComponentName, ParsedService> mServices = new ArrayMap<>();
1769     }
1770 
1771     public static final class InstantAppIntentResolver
1772             extends IntentResolver<AuxiliaryResolveInfo.AuxiliaryFilter,
1773             AuxiliaryResolveInfo.AuxiliaryFilter> {
1774         /**
1775          * The result that has the highest defined order. Ordering applies on a
1776          * per-package basis. Mapping is from package name to Pair of order and
1777          * EphemeralResolveInfo.
1778          * <p>
1779          * NOTE: This is implemented as a field variable for convenience and efficiency.
1780          * By having a field variable, we're able to track filter ordering as soon as
1781          * a non-zero order is defined. Otherwise, multiple loops across the result set
1782          * would be needed to apply ordering. If the intent resolver becomes re-entrant,
1783          * this needs to be contained entirely within {@link #filterResults}.
1784          */
1785         final ArrayMap<String, Pair<Integer, InstantAppResolveInfo>> mOrderResult =
1786                 new ArrayMap<>();
1787 
1788         @NonNull
1789         private final UserManagerService mUserManager;
1790 
InstantAppIntentResolver(@onNull UserManagerService userManager)1791         public InstantAppIntentResolver(@NonNull UserManagerService userManager) {
1792             mUserManager = userManager;
1793         }
1794 
1795         @Override
newArray(int size)1796         protected AuxiliaryResolveInfo.AuxiliaryFilter[] newArray(int size) {
1797             return new AuxiliaryResolveInfo.AuxiliaryFilter[size];
1798         }
1799 
1800         @Override
isPackageForFilter(String packageName, AuxiliaryResolveInfo.AuxiliaryFilter responseObj)1801         protected boolean isPackageForFilter(String packageName,
1802                 AuxiliaryResolveInfo.AuxiliaryFilter responseObj) {
1803             return true;
1804         }
1805 
1806         @Override
newResult(@onNull Computer computer, AuxiliaryResolveInfo.AuxiliaryFilter responseObj, int match, int userId, long customFlags)1807         protected AuxiliaryResolveInfo.AuxiliaryFilter newResult(@NonNull Computer computer,
1808                 AuxiliaryResolveInfo.AuxiliaryFilter responseObj, int match, int userId,
1809                 long customFlags) {
1810             if (!mUserManager.exists(userId)) {
1811                 return null;
1812             }
1813             final String packageName = responseObj.resolveInfo.getPackageName();
1814             final Integer order = responseObj.getOrder();
1815             final Pair<Integer, InstantAppResolveInfo> lastOrderResult =
1816                     mOrderResult.get(packageName);
1817             // ordering is enabled and this item's order isn't high enough
1818             if (lastOrderResult != null && lastOrderResult.first >= order) {
1819                 return null;
1820             }
1821             final InstantAppResolveInfo res = responseObj.resolveInfo;
1822             if (order > 0) {
1823                 // non-zero order, enable ordering
1824                 mOrderResult.put(packageName, new Pair<>(order, res));
1825             }
1826             return responseObj;
1827         }
1828 
1829         @Override
filterResults(List<AuxiliaryResolveInfo.AuxiliaryFilter> results)1830         protected void filterResults(List<AuxiliaryResolveInfo.AuxiliaryFilter> results) {
1831             // only do work if ordering is enabled [most of the time it won't be]
1832             if (mOrderResult.size() == 0) {
1833                 return;
1834             }
1835             int resultSize = results.size();
1836             for (int i = 0; i < resultSize; i++) {
1837                 final InstantAppResolveInfo info = results.get(i).resolveInfo;
1838                 final String packageName = info.getPackageName();
1839                 final Pair<Integer, InstantAppResolveInfo> savedInfo =
1840                         mOrderResult.get(packageName);
1841                 if (savedInfo == null) {
1842                     // package doesn't having ordering
1843                     continue;
1844                 }
1845                 if (savedInfo.second == info) {
1846                     // circled back to the highest ordered item; remove from order list
1847                     mOrderResult.remove(packageName);
1848                     if (mOrderResult.size() == 0) {
1849                         // no more ordered items
1850                         break;
1851                     }
1852                     continue;
1853                 }
1854                 // item has a worse order, remove it from the result list
1855                 results.remove(i);
1856                 resultSize--;
1857                 i--;
1858             }
1859         }
1860 
1861         @Override
getIntentFilter( @onNull AuxiliaryResolveInfo.AuxiliaryFilter input)1862         protected IntentFilter getIntentFilter(
1863                 @NonNull AuxiliaryResolveInfo.AuxiliaryFilter input) {
1864             return input;
1865         }
1866     }
1867 
1868     /**
1869      * Removes MIME type from the group, by delegating to IntentResolvers
1870      * @return true if any intent filters were changed due to this update
1871      */
updateMimeGroup(@onNull Computer computer, String packageName, String group)1872     public boolean updateMimeGroup(@NonNull Computer computer, String packageName, String group) {
1873         boolean hasChanges = false;
1874         synchronized (mLock) {
1875             hasChanges |= mActivities.updateMimeGroup(computer, packageName, group);
1876             hasChanges |= mProviders.updateMimeGroup(computer, packageName, group);
1877             hasChanges |= mReceivers.updateMimeGroup(computer, packageName, group);
1878             hasChanges |= mServices.updateMimeGroup(computer, packageName, group);
1879             if (hasChanges) {
1880                 onChanged();
1881             }
1882         }
1883         return hasChanges;
1884     }
1885 }
1886