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