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