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