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