1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.pm; 18 19 import static android.content.pm.PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER; 20 import static android.content.pm.PackageManagerInternal.PACKAGE_SETUP_WIZARD; 21 22 import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING; 23 import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE; 24 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 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.PackageManagerInternal; 36 import android.content.pm.PackageUserState; 37 import android.content.pm.ProviderInfo; 38 import android.content.pm.ResolveInfo; 39 import android.content.pm.ServiceInfo; 40 import android.content.pm.parsing.component.ParsedActivity; 41 import android.content.pm.parsing.component.ParsedComponent; 42 import android.content.pm.parsing.component.ParsedIntentInfo; 43 import android.content.pm.parsing.component.ParsedMainComponent; 44 import android.content.pm.parsing.component.ParsedProvider; 45 import android.content.pm.parsing.component.ParsedService; 46 import android.os.UserHandle; 47 import android.util.ArrayMap; 48 import android.util.ArraySet; 49 import android.util.DebugUtils; 50 import android.util.Log; 51 import android.util.LogPrinter; 52 import android.util.Pair; 53 import android.util.Slog; 54 55 import com.android.internal.annotations.GuardedBy; 56 import com.android.internal.annotations.VisibleForTesting; 57 import com.android.internal.util.ArrayUtils; 58 import com.android.server.IntentResolver; 59 import com.android.server.pm.parsing.PackageInfoUtils; 60 import com.android.server.pm.parsing.PackageInfoUtils.CachedApplicationInfoGenerator; 61 import com.android.server.pm.parsing.pkg.AndroidPackage; 62 import com.android.server.utils.Snappable; 63 import com.android.server.utils.SnapshotCache; 64 import com.android.server.utils.WatchableImpl; 65 66 import java.io.PrintWriter; 67 import java.util.ArrayList; 68 import java.util.Collections; 69 import java.util.Comparator; 70 import java.util.Iterator; 71 import java.util.List; 72 import java.util.Map; 73 import java.util.Objects; 74 import java.util.Set; 75 import java.util.function.Function; 76 77 /** Resolves all Android component types [activities, services, providers and receivers]. */ 78 public class ComponentResolver 79 extends WatchableImpl 80 implements Snappable { 81 private static final boolean DEBUG = false; 82 private static final String TAG = "PackageManager"; 83 private static final boolean DEBUG_FILTERS = false; 84 private static final boolean DEBUG_SHOW_INFO = false; 85 86 // Convenience function to report that this object has changed. onChanged()87 private void onChanged() { 88 dispatchChange(this); 89 } 90 91 /** 92 * The set of all protected actions [i.e. those actions for which a high priority 93 * intent filter is disallowed]. 94 */ 95 private static final Set<String> PROTECTED_ACTIONS = new ArraySet<>(); 96 static { 97 PROTECTED_ACTIONS.add(Intent.ACTION_SEND); 98 PROTECTED_ACTIONS.add(Intent.ACTION_SENDTO); 99 PROTECTED_ACTIONS.add(Intent.ACTION_SEND_MULTIPLE); 100 PROTECTED_ACTIONS.add(Intent.ACTION_VIEW); 101 } 102 103 static final Comparator<ResolveInfo> RESOLVE_PRIORITY_SORTER = (r1, r2) -> { 104 int v1 = r1.priority; 105 int v2 = r2.priority; 106 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2); 107 if (v1 != v2) { 108 return (v1 > v2) ? -1 : 1; 109 } 110 v1 = r1.preferredOrder; 111 v2 = r2.preferredOrder; 112 if (v1 != v2) { 113 return (v1 > v2) ? -1 : 1; 114 } 115 if (r1.isDefault != r2.isDefault) { 116 return r1.isDefault ? -1 : 1; 117 } 118 v1 = r1.match; 119 v2 = r2.match; 120 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2); 121 if (v1 != v2) { 122 return (v1 > v2) ? -1 : 1; 123 } 124 if (r1.system != r2.system) { 125 return r1.system ? -1 : 1; 126 } 127 if (r1.activityInfo != null) { 128 return r1.activityInfo.packageName.compareTo(r2.activityInfo.packageName); 129 } 130 if (r1.serviceInfo != null) { 131 return r1.serviceInfo.packageName.compareTo(r2.serviceInfo.packageName); 132 } 133 if (r1.providerInfo != null) { 134 return r1.providerInfo.packageName.compareTo(r2.providerInfo.packageName); 135 } 136 return 0; 137 }; 138 139 private static UserManagerService sUserManager; 140 private static PackageManagerInternal sPackageManagerInternal; 141 142 /** 143 * Locking within package manager is going to get worse before it gets better. Currently, 144 * we need to share the {@link PackageManagerService} lock to prevent deadlocks. This occurs 145 * because in order to safely query the resolvers, we need to obtain this lock. However, 146 * during resolution, we call into the {@link PackageManagerService}. This is _not_ to 147 * operate on data controlled by the service proper, but, to check the state of package 148 * settings [contained in a {@link Settings} object]. However, the {@link Settings} object 149 * happens to be protected by the main {@link PackageManagerService} lock. 150 * <p> 151 * There are a couple potential solutions. 152 * <ol> 153 * <li>Split all of our locks into reader/writer locks. This would allow multiple, 154 * simultaneous read operations and means we don't have to be as cautious about lock 155 * layering. Only when we want to perform a write operation will we ever be in a 156 * position to deadlock the system.</li> 157 * <li>Use the same lock across all classes within the {@code com.android.server.pm} 158 * package. By unifying the lock object, we remove any potential lock layering issues 159 * within the package manager. However, we already have a sense that this lock is 160 * heavily contended and merely adding more dependencies on it will have further 161 * impact.</li> 162 * <li>Implement proper lock ordering within the package manager. By defining the 163 * relative layer of the component [eg. {@link PackageManagerService} is at the top. 164 * Somewhere in the middle would be {@link ComponentResolver}. At the very bottom 165 * would be {@link Settings}.] The ordering would allow higher layers to hold their 166 * lock while calling down. Lower layers must relinquish their lock before calling up. 167 * Since {@link Settings} would live at the lowest layer, the {@link ComponentResolver} 168 * would be able to hold its lock while checking the package setting state.</li> 169 * </ol> 170 */ 171 private final PackageManagerTracedLock mLock; 172 173 /** All available activities, for your resolving pleasure. */ 174 @GuardedBy("mLock") 175 private final ActivityIntentResolver mActivities; 176 177 /** All available providers, for your resolving pleasure. */ 178 @GuardedBy("mLock") 179 private final ProviderIntentResolver mProviders; 180 181 /** All available receivers, for your resolving pleasure. */ 182 @GuardedBy("mLock") 183 private final ReceiverIntentResolver mReceivers; 184 185 /** All available services, for your resolving pleasure. */ 186 @GuardedBy("mLock") 187 private final ServiceIntentResolver mServices; 188 189 /** Mapping from provider authority [first directory in content URI codePath) to provider. */ 190 @GuardedBy("mLock") 191 private final ArrayMap<String, ParsedProvider> mProvidersByAuthority; 192 193 /** Whether or not processing protected filters should be deferred. */ 194 private boolean mDeferProtectedFilters = true; 195 196 /** 197 * Tracks high priority intent filters for protected actions. During boot, certain 198 * filter actions are protected and should never be allowed to have a high priority 199 * intent filter for them. However, there is one, and only one exception -- the 200 * setup wizard. It must be able to define a high priority intent filter for these 201 * actions to ensure there are no escapes from the wizard. We need to delay processing 202 * of these during boot as we need to inspect at all of the intent filters on the 203 * /system partition in order to know which component is the setup wizard. This can 204 * only ever be non-empty if {@link #mDeferProtectedFilters} is {@code true}. 205 * 206 * This is a pair of component package name to actual filter, because we don't store the 207 * name inside the filter. It's technically independent of the component it's contained in. 208 */ 209 private List<Pair<ParsedMainComponent, ParsedIntentInfo>> mProtectedFilters; 210 ComponentResolver(UserManagerService userManager, PackageManagerInternal packageManagerInternal, PackageManagerTracedLock lock)211 ComponentResolver(UserManagerService userManager, 212 PackageManagerInternal packageManagerInternal, 213 PackageManagerTracedLock lock) { 214 sPackageManagerInternal = packageManagerInternal; 215 sUserManager = userManager; 216 mLock = lock; 217 218 mActivities = new ActivityIntentResolver(); 219 mProviders = new ProviderIntentResolver(); 220 mReceivers = new ReceiverIntentResolver(); 221 mServices = new ServiceIntentResolver(); 222 mProvidersByAuthority = new ArrayMap<>(); 223 mDeferProtectedFilters = true; 224 225 mSnapshot = new SnapshotCache<ComponentResolver>(this, this) { 226 @Override 227 public ComponentResolver createSnapshot() { 228 return new ComponentResolver(mSource); 229 }}; 230 } 231 232 // Copy constructor used in creating snapshots. ComponentResolver(ComponentResolver orig)233 private ComponentResolver(ComponentResolver orig) { 234 // Do not set the static variables that are set in the default constructor. Do 235 // create a new object for the lock. The snapshot is read-only, so a lock is not 236 // strictly required. However, the current code is simpler if the lock exists, 237 // but does not contend with any outside class. 238 // TODO: make the snapshot lock-free 239 mLock = new PackageManagerTracedLock(); 240 241 mActivities = new ActivityIntentResolver(orig.mActivities); 242 mProviders = new ProviderIntentResolver(orig.mProviders); 243 mReceivers = new ReceiverIntentResolver(orig.mReceivers); 244 mServices = new ServiceIntentResolver(orig.mServices); 245 mProvidersByAuthority = new ArrayMap<>(orig.mProvidersByAuthority); 246 mDeferProtectedFilters = orig.mDeferProtectedFilters; 247 mProtectedFilters = (mProtectedFilters == null) 248 ? null 249 : new ArrayList<>(orig.mProtectedFilters); 250 251 mSnapshot = null; 252 } 253 254 final SnapshotCache<ComponentResolver> mSnapshot; 255 256 /** 257 * Create a snapshot. 258 */ snapshot()259 public ComponentResolver snapshot() { 260 return mSnapshot.snapshot(); 261 } 262 263 264 /** Returns the given activity */ 265 @Nullable 266 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) getActivity(@onNull ComponentName component)267 public ParsedActivity getActivity(@NonNull ComponentName component) { 268 synchronized (mLock) { 269 return mActivities.mActivities.get(component); 270 } 271 } 272 273 /** Returns the given provider */ 274 @Nullable getProvider(@onNull ComponentName component)275 ParsedProvider getProvider(@NonNull ComponentName component) { 276 synchronized (mLock) { 277 return mProviders.mProviders.get(component); 278 } 279 } 280 281 /** Returns the given receiver */ 282 @Nullable getReceiver(@onNull ComponentName component)283 ParsedActivity getReceiver(@NonNull ComponentName component) { 284 synchronized (mLock) { 285 return mReceivers.mActivities.get(component); 286 } 287 } 288 289 /** Returns the given service */ 290 @Nullable getService(@onNull ComponentName component)291 ParsedService getService(@NonNull ComponentName component) { 292 synchronized (mLock) { 293 return mServices.mServices.get(component); 294 } 295 } 296 297 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) componentExists(@onNull ComponentName componentName)298 public boolean componentExists(@NonNull ComponentName componentName) { 299 synchronized (mLock) { 300 ParsedMainComponent component = mActivities.mActivities.get(componentName); 301 if (component != null) { 302 return true; 303 } 304 component = mReceivers.mActivities.get(componentName); 305 if (component != null) { 306 return true; 307 } 308 component = mServices.mServices.get(componentName); 309 if (component != null) { 310 return true; 311 } 312 return mProviders.mProviders.get(componentName) != null; 313 } 314 } 315 316 @Nullable queryActivities(Intent intent, String resolvedType, int flags, int userId)317 List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags, 318 int userId) { 319 synchronized (mLock) { 320 return mActivities.queryIntent(intent, resolvedType, flags, userId); 321 } 322 } 323 324 @Nullable queryActivities(Intent intent, String resolvedType, int flags, List<ParsedActivity> activities, int userId)325 List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags, 326 List<ParsedActivity> activities, int userId) { 327 synchronized (mLock) { 328 return mActivities.queryIntentForPackage( 329 intent, resolvedType, flags, activities, userId); 330 } 331 } 332 333 @Nullable queryProviders(Intent intent, String resolvedType, int flags, int userId)334 List<ResolveInfo> queryProviders(Intent intent, String resolvedType, int flags, int userId) { 335 synchronized (mLock) { 336 return mProviders.queryIntent(intent, resolvedType, flags, userId); 337 } 338 } 339 340 @Nullable queryProviders(Intent intent, String resolvedType, int flags, List<ParsedProvider> providers, int userId)341 List<ResolveInfo> queryProviders(Intent intent, String resolvedType, int flags, 342 List<ParsedProvider> providers, int userId) { 343 synchronized (mLock) { 344 return mProviders.queryIntentForPackage(intent, resolvedType, flags, providers, userId); 345 } 346 } 347 348 @Nullable queryProviders(String processName, String metaDataKey, int uid, int flags, int userId)349 List<ProviderInfo> queryProviders(String processName, String metaDataKey, int uid, int flags, 350 int userId) { 351 if (!sUserManager.exists(userId)) { 352 return null; 353 } 354 List<ProviderInfo> providerList = null; 355 CachedApplicationInfoGenerator appInfoGenerator = null; 356 synchronized (mLock) { 357 for (int i = mProviders.mProviders.size() - 1; i >= 0; --i) { 358 final ParsedProvider p = mProviders.mProviders.valueAt(i); 359 if (p.getAuthority() == null) { 360 continue; 361 } 362 363 final PackageSetting ps = 364 (PackageSetting) sPackageManagerInternal.getPackageSetting( 365 p.getPackageName()); 366 if (ps == null) { 367 continue; 368 } 369 370 AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName()); 371 if (pkg == null) { 372 continue; 373 } 374 375 if (processName != null && (!p.getProcessName().equals(processName) 376 || !UserHandle.isSameApp(pkg.getUid(), uid))) { 377 continue; 378 } 379 // See PM.queryContentProviders()'s javadoc for why we have the metaData parameter. 380 if (metaDataKey != null 381 && (p.getMetaData() == null || !p.getMetaData().containsKey(metaDataKey))) { 382 continue; 383 } 384 if (appInfoGenerator == null) { 385 appInfoGenerator = new CachedApplicationInfoGenerator(); 386 } 387 final PackageUserState state = ps.readUserState(userId); 388 final ApplicationInfo appInfo = 389 appInfoGenerator.generate(pkg, flags, state, userId, ps); 390 if (appInfo == null) { 391 continue; 392 } 393 394 final ProviderInfo info = PackageInfoUtils.generateProviderInfo( 395 pkg, p, flags, state, appInfo, userId, ps); 396 if (info == null) { 397 continue; 398 } 399 if (providerList == null) { 400 providerList = new ArrayList<>(i + 1); 401 } 402 providerList.add(info); 403 } 404 } 405 return providerList; 406 } 407 408 @Nullable queryProvider(String authority, int flags, int userId)409 ProviderInfo queryProvider(String authority, int flags, int userId) { 410 synchronized (mLock) { 411 final ParsedProvider p = mProvidersByAuthority.get(authority); 412 if (p == null) { 413 return null; 414 } 415 final PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting( 416 p.getPackageName()); 417 if (ps == null) { 418 return null; 419 } 420 final AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName()); 421 if (pkg == null) { 422 return null; 423 } 424 final PackageUserState state = ps.readUserState(userId); 425 ApplicationInfo appInfo = PackageInfoUtils.generateApplicationInfo( 426 pkg, flags, state, userId, ps); 427 if (appInfo == null) { 428 return null; 429 } 430 return PackageInfoUtils.generateProviderInfo(pkg, p, flags, state, appInfo, userId, ps); 431 } 432 } 433 querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo, boolean safeMode, int userId)434 void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo, boolean safeMode, 435 int userId) { 436 synchronized (mLock) { 437 CachedApplicationInfoGenerator appInfoGenerator = null; 438 for (int i = mProvidersByAuthority.size() - 1; i >= 0; --i) { 439 final ParsedProvider p = mProvidersByAuthority.valueAt(i); 440 if (!p.isSyncable()) { 441 continue; 442 } 443 444 final PackageSetting ps = 445 (PackageSetting) sPackageManagerInternal.getPackageSetting( 446 p.getPackageName()); 447 if (ps == null) { 448 continue; 449 } 450 451 final AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName()); 452 if (pkg == null) { 453 continue; 454 } 455 456 if (safeMode && !pkg.isSystem()) { 457 continue; 458 } 459 if (appInfoGenerator == null) { 460 appInfoGenerator = new CachedApplicationInfoGenerator(); 461 } 462 final PackageUserState state = ps.readUserState(userId); 463 final ApplicationInfo appInfo = 464 appInfoGenerator.generate(pkg, 0, state, userId, ps); 465 if (appInfo == null) { 466 continue; 467 } 468 469 final ProviderInfo info = PackageInfoUtils.generateProviderInfo( 470 pkg, p, 0, state, appInfo, userId, ps); 471 if (info == null) { 472 continue; 473 } 474 outNames.add(mProvidersByAuthority.keyAt(i)); 475 outInfo.add(info); 476 } 477 } 478 } 479 480 @Nullable queryReceivers(Intent intent, String resolvedType, int flags, int userId)481 List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags, int userId) { 482 synchronized (mLock) { 483 return mReceivers.queryIntent(intent, resolvedType, flags, userId); 484 } 485 } 486 487 @Nullable queryReceivers(Intent intent, String resolvedType, int flags, List<ParsedActivity> receivers, int userId)488 List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags, 489 List<ParsedActivity> receivers, int userId) { 490 synchronized (mLock) { 491 return mReceivers.queryIntentForPackage(intent, resolvedType, flags, receivers, userId); 492 } 493 } 494 495 @Nullable queryServices(Intent intent, String resolvedType, int flags, int userId)496 List<ResolveInfo> queryServices(Intent intent, String resolvedType, int flags, int userId) { 497 synchronized (mLock) { 498 return mServices.queryIntent(intent, resolvedType, flags, userId); 499 } 500 } 501 502 @Nullable queryServices(Intent intent, String resolvedType, int flags, List<ParsedService> services, int userId)503 List<ResolveInfo> queryServices(Intent intent, String resolvedType, int flags, 504 List<ParsedService> services, int userId) { 505 synchronized (mLock) { 506 return mServices.queryIntentForPackage(intent, resolvedType, flags, services, userId); 507 } 508 } 509 510 /** Returns {@code true} if the given activity is defined by some package */ isActivityDefined(ComponentName component)511 boolean isActivityDefined(ComponentName component) { 512 synchronized (mLock) { 513 return mActivities.mActivities.get(component) != null; 514 } 515 } 516 517 /** Asserts none of the providers defined in the given package haven't already been defined. */ assertProvidersNotDefined(AndroidPackage pkg)518 void assertProvidersNotDefined(AndroidPackage pkg) throws PackageManagerException { 519 synchronized (mLock) { 520 assertProvidersNotDefinedLocked(pkg); 521 } 522 } 523 524 /** Add all components defined in the given package to the internal structures. */ addAllComponents(AndroidPackage pkg, boolean chatty)525 void addAllComponents(AndroidPackage pkg, boolean chatty) { 526 final ArrayList<Pair<ParsedActivity, ParsedIntentInfo>> newIntents = new ArrayList<>(); 527 synchronized (mLock) { 528 addActivitiesLocked(pkg, newIntents, chatty); 529 addReceiversLocked(pkg, chatty); 530 addProvidersLocked(pkg, chatty); 531 addServicesLocked(pkg, chatty); 532 onChanged(); 533 } 534 // expect single setupwizard package 535 final String setupWizardPackage = ArrayUtils.firstOrNull( 536 sPackageManagerInternal.getKnownPackageNames( 537 PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM)); 538 539 for (int i = newIntents.size() - 1; i >= 0; --i) { 540 final Pair<ParsedActivity, ParsedIntentInfo> pair = newIntents.get(i); 541 final PackageSetting disabledPkgSetting = (PackageSetting) sPackageManagerInternal 542 .getDisabledSystemPackage(pair.first.getPackageName()); 543 final AndroidPackage disabledPkg = 544 disabledPkgSetting == null ? null : disabledPkgSetting.pkg; 545 final List<ParsedActivity> systemActivities = 546 disabledPkg != null ? disabledPkg.getActivities() : null; 547 adjustPriority(systemActivities, pair.first, pair.second, setupWizardPackage); 548 onChanged(); 549 } 550 } 551 552 /** Removes all components defined in the given package from the internal structures. */ removeAllComponents(AndroidPackage pkg, boolean chatty)553 void removeAllComponents(AndroidPackage pkg, boolean chatty) { 554 synchronized (mLock) { 555 removeAllComponentsLocked(pkg, chatty); 556 onChanged(); 557 } 558 } 559 560 /** 561 * Reprocess any protected filters that have been deferred. At this point, we've scanned 562 * all of the filters defined on the /system partition and know the special components. 563 */ fixProtectedFilterPriorities()564 void fixProtectedFilterPriorities() { 565 synchronized (mLock) { 566 if (!mDeferProtectedFilters) { 567 return; 568 } 569 mDeferProtectedFilters = false; 570 571 if (mProtectedFilters == null || mProtectedFilters.size() == 0) { 572 return; 573 } 574 final List<Pair<ParsedMainComponent, ParsedIntentInfo>> protectedFilters = 575 mProtectedFilters; 576 mProtectedFilters = null; 577 578 // expect single setupwizard package 579 final String setupWizardPackage = ArrayUtils.firstOrNull( 580 sPackageManagerInternal.getKnownPackageNames( 581 PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM)); 582 583 if (DEBUG_FILTERS && setupWizardPackage == null) { 584 Slog.i(TAG, "No setup wizard;" 585 + " All protected intents capped to priority 0"); 586 } 587 for (int i = protectedFilters.size() - 1; i >= 0; --i) { 588 final Pair<ParsedMainComponent, ParsedIntentInfo> pair = protectedFilters.get(i); 589 ParsedMainComponent component = pair.first; 590 ParsedIntentInfo filter = pair.second; 591 String packageName = component.getPackageName(); 592 String className = component.getClassName(); 593 if (packageName.equals(setupWizardPackage)) { 594 if (DEBUG_FILTERS) { 595 Slog.i(TAG, "Found setup wizard;" 596 + " allow priority " + filter.getPriority() + ";" 597 + " package: " + packageName 598 + " activity: " + className 599 + " priority: " + filter.getPriority()); 600 } 601 // skip setup wizard; allow it to keep the high priority filter 602 continue; 603 } 604 if (DEBUG_FILTERS) { 605 Slog.i(TAG, "Protected action; cap priority to 0;" 606 + " package: " + packageName 607 + " activity: " + className 608 + " origPrio: " + filter.getPriority()); 609 } 610 filter.setPriority(0); 611 } 612 onChanged(); 613 } 614 } 615 dumpActivityResolvers(PrintWriter pw, DumpState dumpState, String packageName)616 void dumpActivityResolvers(PrintWriter pw, DumpState dumpState, String packageName) { 617 if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:" 618 : "Activity Resolver Table:", " ", packageName, 619 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) { 620 dumpState.setTitlePrinted(true); 621 } 622 } 623 dumpProviderResolvers(PrintWriter pw, DumpState dumpState, String packageName)624 void dumpProviderResolvers(PrintWriter pw, DumpState dumpState, String packageName) { 625 if (mProviders.dump(pw, dumpState.getTitlePrinted() ? "\nProvider Resolver Table:" 626 : "Provider Resolver Table:", " ", packageName, 627 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) { 628 dumpState.setTitlePrinted(true); 629 } 630 } 631 dumpReceiverResolvers(PrintWriter pw, DumpState dumpState, String packageName)632 void dumpReceiverResolvers(PrintWriter pw, DumpState dumpState, String packageName) { 633 if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:" 634 : "Receiver Resolver Table:", " ", packageName, 635 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) { 636 dumpState.setTitlePrinted(true); 637 } 638 } 639 dumpServiceResolvers(PrintWriter pw, DumpState dumpState, String packageName)640 void dumpServiceResolvers(PrintWriter pw, DumpState dumpState, String packageName) { 641 if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:" 642 : "Service Resolver Table:", " ", packageName, 643 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) { 644 dumpState.setTitlePrinted(true); 645 } 646 } 647 dumpContentProviders(PrintWriter pw, DumpState dumpState, String packageName)648 void dumpContentProviders(PrintWriter pw, DumpState dumpState, String packageName) { 649 boolean printedSomething = false; 650 for (ParsedProvider p : mProviders.mProviders.values()) { 651 if (packageName != null && !packageName.equals(p.getPackageName())) { 652 continue; 653 } 654 if (!printedSomething) { 655 if (dumpState.onTitlePrinted()) { 656 pw.println(); 657 } 658 pw.println("Registered ContentProviders:"); 659 printedSomething = true; 660 } 661 pw.print(" "); 662 ComponentName.printShortString(pw, p.getPackageName(), p.getName()); 663 pw.println(":"); 664 pw.print(" "); 665 pw.println(p.toString()); 666 } 667 printedSomething = false; 668 for (Map.Entry<String, ParsedProvider> entry : 669 mProvidersByAuthority.entrySet()) { 670 ParsedProvider p = entry.getValue(); 671 if (packageName != null && !packageName.equals(p.getPackageName())) { 672 continue; 673 } 674 if (!printedSomething) { 675 if (dumpState.onTitlePrinted()) { 676 pw.println(); 677 } 678 pw.println("ContentProvider Authorities:"); 679 printedSomething = true; 680 } 681 pw.print(" ["); pw.print(entry.getKey()); pw.println("]:"); 682 pw.print(" "); pw.println(p.toString()); 683 684 AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName()); 685 686 if (pkg != null) { 687 pw.print(" applicationInfo="); pw.println(pkg.toAppInfoWithoutState()); 688 } 689 } 690 } 691 dumpServicePermissions(PrintWriter pw, DumpState dumpState)692 void dumpServicePermissions(PrintWriter pw, DumpState dumpState) { 693 if (dumpState.onTitlePrinted()) pw.println(); 694 pw.println("Service permissions:"); 695 696 final Iterator<Pair<ParsedService, ParsedIntentInfo>> filterIterator = 697 mServices.filterIterator(); 698 while (filterIterator.hasNext()) { 699 final Pair<ParsedService, ParsedIntentInfo> pair = filterIterator.next(); 700 ParsedService service = pair.first; 701 702 final String permission = service.getPermission(); 703 if (permission != null) { 704 pw.print(" "); 705 pw.print(service.getComponentName().flattenToShortString()); 706 pw.print(": "); 707 pw.println(permission); 708 } 709 } 710 } 711 712 @GuardedBy("mLock") addActivitiesLocked(AndroidPackage pkg, List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents, boolean chatty)713 private void addActivitiesLocked(AndroidPackage pkg, 714 List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents, boolean chatty) { 715 final int activitiesSize = ArrayUtils.size(pkg.getActivities()); 716 StringBuilder r = null; 717 for (int i = 0; i < activitiesSize; i++) { 718 ParsedActivity a = pkg.getActivities().get(i); 719 mActivities.addActivity(a, "activity", newIntents); 720 if (DEBUG_PACKAGE_SCANNING && chatty) { 721 if (r == null) { 722 r = new StringBuilder(256); 723 } else { 724 r.append(' '); 725 } 726 r.append(a.getName()); 727 } 728 } 729 if (DEBUG_PACKAGE_SCANNING && chatty) { 730 Log.d(TAG, " Activities: " + (r == null ? "<NONE>" : r)); 731 } 732 } 733 734 @GuardedBy("mLock") addProvidersLocked(AndroidPackage pkg, boolean chatty)735 private void addProvidersLocked(AndroidPackage pkg, boolean chatty) { 736 final int providersSize = ArrayUtils.size(pkg.getProviders()); 737 StringBuilder r = null; 738 for (int i = 0; i < providersSize; i++) { 739 ParsedProvider p = pkg.getProviders().get(i); 740 mProviders.addProvider(p); 741 if (p.getAuthority() != null) { 742 String[] names = p.getAuthority().split(";"); 743 744 // TODO(b/135203078): Remove this mutation 745 p.setAuthority(null); 746 for (int j = 0; j < names.length; j++) { 747 if (j == 1 && p.isSyncable()) { 748 // We only want the first authority for a provider to possibly be 749 // syncable, so if we already added this provider using a different 750 // authority clear the syncable flag. We copy the provider before 751 // changing it because the mProviders object contains a reference 752 // to a provider that we don't want to change. 753 // Only do this for the second authority since the resulting provider 754 // object can be the same for all future authorities for this provider. 755 p = new ParsedProvider(p); 756 p.setSyncable(false); 757 } 758 if (!mProvidersByAuthority.containsKey(names[j])) { 759 mProvidersByAuthority.put(names[j], p); 760 if (p.getAuthority() == null) { 761 p.setAuthority(names[j]); 762 } else { 763 p.setAuthority(p.getAuthority() + ";" + names[j]); 764 } 765 if (DEBUG_PACKAGE_SCANNING && chatty) { 766 Log.d(TAG, "Registered content provider: " + names[j] 767 + ", className = " + p.getName() 768 + ", isSyncable = " + p.isSyncable()); 769 } 770 } else { 771 final ParsedProvider other = 772 mProvidersByAuthority.get(names[j]); 773 final ComponentName component = 774 (other != null && other.getComponentName() != null) 775 ? other.getComponentName() : null; 776 final String packageName = 777 component != null ? component.getPackageName() : "?"; 778 Slog.w(TAG, "Skipping provider name " + names[j] 779 + " (in package " + pkg.getPackageName() + ")" 780 + ": name already used by " + packageName); 781 } 782 } 783 } 784 if (DEBUG_PACKAGE_SCANNING && chatty) { 785 if (r == null) { 786 r = new StringBuilder(256); 787 } else { 788 r.append(' '); 789 } 790 r.append(p.getName()); 791 } 792 } 793 if (DEBUG_PACKAGE_SCANNING && chatty) { 794 Log.d(TAG, " Providers: " + (r == null ? "<NONE>" : r)); 795 } 796 } 797 798 @GuardedBy("mLock") addReceiversLocked(AndroidPackage pkg, boolean chatty)799 private void addReceiversLocked(AndroidPackage pkg, boolean chatty) { 800 final int receiversSize = ArrayUtils.size(pkg.getReceivers()); 801 StringBuilder r = null; 802 for (int i = 0; i < receiversSize; i++) { 803 ParsedActivity a = pkg.getReceivers().get(i); 804 mReceivers.addActivity(a, "receiver", null); 805 if (DEBUG_PACKAGE_SCANNING && chatty) { 806 if (r == null) { 807 r = new StringBuilder(256); 808 } else { 809 r.append(' '); 810 } 811 r.append(a.getName()); 812 } 813 } 814 if (DEBUG_PACKAGE_SCANNING && chatty) { 815 Log.d(TAG, " Receivers: " + (r == null ? "<NONE>" : r)); 816 } 817 } 818 819 @GuardedBy("mLock") addServicesLocked(AndroidPackage pkg, boolean chatty)820 private void addServicesLocked(AndroidPackage pkg, boolean chatty) { 821 final int servicesSize = ArrayUtils.size(pkg.getServices()); 822 StringBuilder r = null; 823 for (int i = 0; i < servicesSize; i++) { 824 ParsedService s = pkg.getServices().get(i); 825 mServices.addService(s); 826 if (DEBUG_PACKAGE_SCANNING && chatty) { 827 if (r == null) { 828 r = new StringBuilder(256); 829 } else { 830 r.append(' '); 831 } 832 r.append(s.getName()); 833 } 834 } 835 if (DEBUG_PACKAGE_SCANNING && chatty) { 836 Log.d(TAG, " Services: " + (r == null ? "<NONE>" : r)); 837 } 838 } 839 840 /** 841 * <em>WARNING</em> for performance reasons, the passed in intentList WILL BE 842 * MODIFIED. Do not pass in a list that should not be changed. 843 */ getIntentListSubset(List<ParsedIntentInfo> intentList, Function<ParsedIntentInfo, Iterator<T>> generator, Iterator<T> searchIterator)844 private static <T> void getIntentListSubset(List<ParsedIntentInfo> intentList, 845 Function<ParsedIntentInfo, Iterator<T>> generator, Iterator<T> searchIterator) { 846 // loop through the set of actions; every one must be found in the intent filter 847 while (searchIterator.hasNext()) { 848 // we must have at least one filter in the list to consider a match 849 if (intentList.size() == 0) { 850 break; 851 } 852 853 final T searchAction = searchIterator.next(); 854 855 // loop through the set of intent filters 856 final Iterator<ParsedIntentInfo> intentIter = intentList.iterator(); 857 while (intentIter.hasNext()) { 858 final ParsedIntentInfo intentInfo = intentIter.next(); 859 boolean selectionFound = false; 860 861 // loop through the intent filter's selection criteria; at least one 862 // of them must match the searched criteria 863 final Iterator<T> intentSelectionIter = generator.apply(intentInfo); 864 while (intentSelectionIter != null && intentSelectionIter.hasNext()) { 865 final T intentSelection = intentSelectionIter.next(); 866 if (intentSelection != null && intentSelection.equals(searchAction)) { 867 selectionFound = true; 868 break; 869 } 870 } 871 872 // the selection criteria wasn't found in this filter's set; this filter 873 // is not a potential match 874 if (!selectionFound) { 875 intentIter.remove(); 876 } 877 } 878 } 879 } 880 isProtectedAction(ParsedIntentInfo filter)881 private static boolean isProtectedAction(ParsedIntentInfo filter) { 882 final Iterator<String> actionsIter = filter.actionsIterator(); 883 while (actionsIter != null && actionsIter.hasNext()) { 884 final String filterAction = actionsIter.next(); 885 if (PROTECTED_ACTIONS.contains(filterAction)) { 886 return true; 887 } 888 } 889 return false; 890 } 891 892 /** 893 * Finds a privileged activity that matches the specified activity names. 894 */ findMatchingActivity( List<ParsedActivity> activityList, ParsedActivity activityInfo)895 private static ParsedActivity findMatchingActivity( 896 List<ParsedActivity> activityList, ParsedActivity activityInfo) { 897 for (ParsedActivity sysActivity : activityList) { 898 if (sysActivity.getName().equals(activityInfo.getName())) { 899 return sysActivity; 900 } 901 if (sysActivity.getName().equals(activityInfo.getTargetActivity())) { 902 return sysActivity; 903 } 904 if (sysActivity.getTargetActivity() != null) { 905 if (sysActivity.getTargetActivity().equals(activityInfo.getName())) { 906 return sysActivity; 907 } 908 if (sysActivity.getTargetActivity().equals(activityInfo.getTargetActivity())) { 909 return sysActivity; 910 } 911 } 912 } 913 return null; 914 } 915 916 /** 917 * Adjusts the priority of the given intent filter according to policy. 918 * <p> 919 * <ul> 920 * <li>The priority for non privileged applications is capped to '0'</li> 921 * <li>The priority for protected actions on privileged applications is capped to '0'</li> 922 * <li>The priority for unbundled updates to privileged applications is capped to the 923 * priority defined on the system partition</li> 924 * </ul> 925 * <p> 926 * <em>NOTE:</em> There is one exception. For security reasons, the setup wizard is 927 * allowed to obtain any priority on any action. 928 */ adjustPriority(List<ParsedActivity> systemActivities, ParsedActivity activity, ParsedIntentInfo intent, String setupWizardPackage)929 private void adjustPriority(List<ParsedActivity> systemActivities, ParsedActivity activity, 930 ParsedIntentInfo intent, String setupWizardPackage) { 931 // nothing to do; priority is fine as-is 932 if (intent.getPriority() <= 0) { 933 return; 934 } 935 936 String packageName = activity.getPackageName(); 937 AndroidPackage pkg = sPackageManagerInternal.getPackage(packageName); 938 939 final boolean privilegedApp = pkg.isPrivileged(); 940 String className = activity.getClassName(); 941 if (!privilegedApp) { 942 // non-privileged applications can never define a priority >0 943 if (DEBUG_FILTERS) { 944 Slog.i(TAG, "Non-privileged app; cap priority to 0;" 945 + " package: " + packageName 946 + " activity: " + className 947 + " origPrio: " + intent.getPriority()); 948 } 949 intent.setPriority(0); 950 return; 951 } 952 953 if (isProtectedAction(intent)) { 954 if (mDeferProtectedFilters) { 955 // We can't deal with these just yet. No component should ever obtain a 956 // >0 priority for a protected actions, with ONE exception -- the setup 957 // wizard. The setup wizard, however, cannot be known until we're able to 958 // query it for the category CATEGORY_SETUP_WIZARD. Which we can't do 959 // until all intent filters have been processed. Chicken, meet egg. 960 // Let the filter temporarily have a high priority and rectify the 961 // priorities after all system packages have been scanned. 962 if (mProtectedFilters == null) { 963 mProtectedFilters = new ArrayList<>(); 964 } 965 mProtectedFilters.add(Pair.create(activity, intent)); 966 if (DEBUG_FILTERS) { 967 Slog.i(TAG, "Protected action; save for later;" 968 + " package: " + packageName 969 + " activity: " + className 970 + " origPrio: " + intent.getPriority()); 971 } 972 } else { 973 if (DEBUG_FILTERS && setupWizardPackage == null) { 974 Slog.i(TAG, "No setup wizard;" 975 + " All protected intents capped to priority 0"); 976 } 977 if (packageName.equals(setupWizardPackage)) { 978 if (DEBUG_FILTERS) { 979 Slog.i(TAG, "Found setup wizard;" 980 + " allow priority " + intent.getPriority() + ";" 981 + " package: " + packageName 982 + " activity: " + className 983 + " priority: " + intent.getPriority()); 984 } 985 // setup wizard gets whatever it wants 986 return; 987 } 988 if (DEBUG_FILTERS) { 989 Slog.i(TAG, "Protected action; cap priority to 0;" 990 + " package: " + packageName 991 + " activity: " + className 992 + " origPrio: " + intent.getPriority()); 993 } 994 intent.setPriority(0); 995 } 996 return; 997 } 998 999 if (systemActivities == null) { 1000 // the system package is not disabled; we're parsing the system partition 1001 1002 // privileged apps on the system image get whatever priority they request 1003 return; 1004 } 1005 1006 // privileged app unbundled update ... try to find the same activity 1007 1008 ParsedActivity foundActivity = findMatchingActivity(systemActivities, activity); 1009 if (foundActivity == null) { 1010 // this is a new activity; it cannot obtain >0 priority 1011 if (DEBUG_FILTERS) { 1012 Slog.i(TAG, "New activity; cap priority to 0;" 1013 + " package: " + packageName 1014 + " activity: " + className 1015 + " origPrio: " + intent.getPriority()); 1016 } 1017 intent.setPriority(0); 1018 return; 1019 } 1020 1021 // found activity, now check for filter equivalence 1022 1023 // a shallow copy is enough; we modify the list, not its contents 1024 final List<ParsedIntentInfo> intentListCopy = 1025 new ArrayList<>(foundActivity.getIntents()); 1026 1027 // find matching action subsets 1028 final Iterator<String> actionsIterator = intent.actionsIterator(); 1029 if (actionsIterator != null) { 1030 getIntentListSubset(intentListCopy, IntentFilter::actionsIterator, actionsIterator); 1031 if (intentListCopy.size() == 0) { 1032 // no more intents to match; we're not equivalent 1033 if (DEBUG_FILTERS) { 1034 Slog.i(TAG, "Mismatched action; cap priority to 0;" 1035 + " package: " + packageName 1036 + " activity: " + className 1037 + " origPrio: " + intent.getPriority()); 1038 } 1039 intent.setPriority(0); 1040 return; 1041 } 1042 } 1043 1044 // find matching category subsets 1045 final Iterator<String> categoriesIterator = intent.categoriesIterator(); 1046 if (categoriesIterator != null) { 1047 getIntentListSubset(intentListCopy, IntentFilter::categoriesIterator, 1048 categoriesIterator); 1049 if (intentListCopy.size() == 0) { 1050 // no more intents to match; we're not equivalent 1051 if (DEBUG_FILTERS) { 1052 Slog.i(TAG, "Mismatched category; cap priority to 0;" 1053 + " package: " + packageName 1054 + " activity: " + className 1055 + " origPrio: " + intent.getPriority()); 1056 } 1057 intent.setPriority(0); 1058 return; 1059 } 1060 } 1061 1062 // find matching schemes subsets 1063 final Iterator<String> schemesIterator = intent.schemesIterator(); 1064 if (schemesIterator != null) { 1065 getIntentListSubset(intentListCopy, IntentFilter::schemesIterator, schemesIterator); 1066 if (intentListCopy.size() == 0) { 1067 // no more intents to match; we're not equivalent 1068 if (DEBUG_FILTERS) { 1069 Slog.i(TAG, "Mismatched scheme; cap priority to 0;" 1070 + " package: " + packageName 1071 + " activity: " + className 1072 + " origPrio: " + intent.getPriority()); 1073 } 1074 intent.setPriority(0); 1075 return; 1076 } 1077 } 1078 1079 // find matching authorities subsets 1080 final Iterator<IntentFilter.AuthorityEntry> authoritiesIterator = 1081 intent.authoritiesIterator(); 1082 if (authoritiesIterator != null) { 1083 getIntentListSubset(intentListCopy, IntentFilter::authoritiesIterator, 1084 authoritiesIterator); 1085 if (intentListCopy.size() == 0) { 1086 // no more intents to match; we're not equivalent 1087 if (DEBUG_FILTERS) { 1088 Slog.i(TAG, "Mismatched authority; cap priority to 0;" 1089 + " package: " + packageName 1090 + " activity: " + className 1091 + " origPrio: " + intent.getPriority()); 1092 } 1093 intent.setPriority(0); 1094 return; 1095 } 1096 } 1097 1098 // we found matching filter(s); app gets the max priority of all intents 1099 int cappedPriority = 0; 1100 for (int i = intentListCopy.size() - 1; i >= 0; --i) { 1101 cappedPriority = Math.max(cappedPriority, intentListCopy.get(i).getPriority()); 1102 } 1103 if (intent.getPriority() > cappedPriority) { 1104 if (DEBUG_FILTERS) { 1105 Slog.i(TAG, "Found matching filter(s);" 1106 + " cap priority to " + cappedPriority + ";" 1107 + " package: " + packageName 1108 + " activity: " + className 1109 + " origPrio: " + intent.getPriority()); 1110 } 1111 intent.setPriority(cappedPriority); 1112 return; 1113 } 1114 // all this for nothing; the requested priority was <= what was on the system 1115 } 1116 1117 @GuardedBy("mLock") removeAllComponentsLocked(AndroidPackage pkg, boolean chatty)1118 private void removeAllComponentsLocked(AndroidPackage pkg, boolean chatty) { 1119 int componentSize; 1120 StringBuilder r; 1121 int i; 1122 1123 componentSize = ArrayUtils.size(pkg.getActivities()); 1124 r = null; 1125 for (i = 0; i < componentSize; i++) { 1126 ParsedActivity a = pkg.getActivities().get(i); 1127 mActivities.removeActivity(a, "activity"); 1128 if (DEBUG_REMOVE && chatty) { 1129 if (r == null) { 1130 r = new StringBuilder(256); 1131 } else { 1132 r.append(' '); 1133 } 1134 r.append(a.getName()); 1135 } 1136 } 1137 if (DEBUG_REMOVE && chatty) { 1138 Log.d(TAG, " Activities: " + (r == null ? "<NONE>" : r)); 1139 } 1140 1141 componentSize = ArrayUtils.size(pkg.getProviders()); 1142 r = null; 1143 for (i = 0; i < componentSize; i++) { 1144 ParsedProvider p = pkg.getProviders().get(i); 1145 mProviders.removeProvider(p); 1146 if (p.getAuthority() == null) { 1147 // Another content provider with this authority existed when this app was 1148 // installed, so this authority is null. Ignore it as we don't have to 1149 // unregister the provider. 1150 continue; 1151 } 1152 String[] names = p.getAuthority().split(";"); 1153 for (int j = 0; j < names.length; j++) { 1154 if (mProvidersByAuthority.get(names[j]) == p) { 1155 mProvidersByAuthority.remove(names[j]); 1156 if (DEBUG_REMOVE && chatty) { 1157 Log.d(TAG, "Unregistered content provider: " + names[j] 1158 + ", className = " + p.getName() + ", isSyncable = " 1159 + p.isSyncable()); 1160 } 1161 } 1162 } 1163 if (DEBUG_REMOVE && chatty) { 1164 if (r == null) { 1165 r = new StringBuilder(256); 1166 } else { 1167 r.append(' '); 1168 } 1169 r.append(p.getName()); 1170 } 1171 } 1172 if (DEBUG_REMOVE && chatty) { 1173 Log.d(TAG, " Providers: " + (r == null ? "<NONE>" : r)); 1174 } 1175 1176 componentSize = ArrayUtils.size(pkg.getReceivers()); 1177 r = null; 1178 for (i = 0; i < componentSize; i++) { 1179 ParsedActivity a = pkg.getReceivers().get(i); 1180 mReceivers.removeActivity(a, "receiver"); 1181 if (DEBUG_REMOVE && chatty) { 1182 if (r == null) { 1183 r = new StringBuilder(256); 1184 } else { 1185 r.append(' '); 1186 } 1187 r.append(a.getName()); 1188 } 1189 } 1190 if (DEBUG_REMOVE && chatty) { 1191 Log.d(TAG, " Receivers: " + (r == null ? "<NONE>" : r)); 1192 } 1193 1194 componentSize = ArrayUtils.size(pkg.getServices()); 1195 r = null; 1196 for (i = 0; i < componentSize; i++) { 1197 ParsedService s = pkg.getServices().get(i); 1198 mServices.removeService(s); 1199 if (DEBUG_REMOVE && chatty) { 1200 if (r == null) { 1201 r = new StringBuilder(256); 1202 } else { 1203 r.append(' '); 1204 } 1205 r.append(s.getName()); 1206 } 1207 } 1208 if (DEBUG_REMOVE && chatty) { 1209 Log.d(TAG, " Services: " + (r == null ? "<NONE>" : r)); 1210 } 1211 } 1212 1213 @GuardedBy("mLock") assertProvidersNotDefinedLocked(AndroidPackage pkg)1214 private void assertProvidersNotDefinedLocked(AndroidPackage pkg) 1215 throws PackageManagerException { 1216 final int providersSize = ArrayUtils.size(pkg.getProviders()); 1217 int i; 1218 for (i = 0; i < providersSize; i++) { 1219 ParsedProvider p = pkg.getProviders().get(i); 1220 if (p.getAuthority() != null) { 1221 final String[] names = p.getAuthority().split(";"); 1222 for (int j = 0; j < names.length; j++) { 1223 if (mProvidersByAuthority.containsKey(names[j])) { 1224 final ParsedProvider other = mProvidersByAuthority.get(names[j]); 1225 final String otherPackageName = 1226 (other != null && other.getComponentName() != null) 1227 ? other.getComponentName().getPackageName() : "?"; 1228 // if we're installing over the same already-installed package, this is ok 1229 if (!otherPackageName.equals(pkg.getPackageName())) { 1230 throw new PackageManagerException( 1231 INSTALL_FAILED_CONFLICTING_PROVIDER, 1232 "Can't install because provider name " + names[j] 1233 + " (in package " + pkg.getPackageName() 1234 + ") is already used by " + otherPackageName); 1235 } 1236 } 1237 } 1238 } 1239 } 1240 } 1241 1242 private abstract static class MimeGroupsAwareIntentResolver<F extends Pair<? 1243 extends ParsedComponent, ParsedIntentInfo>, R> 1244 extends IntentResolver<F, R> { 1245 private final ArrayMap<String, F[]> mMimeGroupToFilter = new ArrayMap<>(); 1246 private boolean mIsUpdatingMimeGroup = false; 1247 1248 // Default constructor MimeGroupsAwareIntentResolver()1249 MimeGroupsAwareIntentResolver() { 1250 } 1251 1252 // Copy constructor used in creating snapshots MimeGroupsAwareIntentResolver(MimeGroupsAwareIntentResolver<F, R> orig)1253 MimeGroupsAwareIntentResolver(MimeGroupsAwareIntentResolver<F, R> orig) { 1254 copyFrom(orig); 1255 copyInto(mMimeGroupToFilter, orig.mMimeGroupToFilter); 1256 mIsUpdatingMimeGroup = orig.mIsUpdatingMimeGroup; 1257 } 1258 1259 @Override addFilter(F f)1260 public void addFilter(F f) { 1261 IntentFilter intentFilter = getIntentFilter(f); 1262 applyMimeGroups(f); 1263 super.addFilter(f); 1264 1265 if (!mIsUpdatingMimeGroup) { 1266 register_intent_filter(f, intentFilter.mimeGroupsIterator(), mMimeGroupToFilter, 1267 " MimeGroup: "); 1268 } 1269 } 1270 1271 @Override removeFilterInternal(F f)1272 protected void removeFilterInternal(F f) { 1273 IntentFilter intentFilter = getIntentFilter(f); 1274 if (!mIsUpdatingMimeGroup) { 1275 unregister_intent_filter(f, intentFilter.mimeGroupsIterator(), mMimeGroupToFilter, 1276 " MimeGroup: "); 1277 } 1278 1279 super.removeFilterInternal(f); 1280 intentFilter.clearDynamicDataTypes(); 1281 } 1282 1283 /** 1284 * Updates MIME group by applying changes to all IntentFilters 1285 * that contain the group and repopulating m*ToFilter maps accordingly 1286 * 1287 * @param packageName package to which MIME group belongs 1288 * @param mimeGroup MIME group to update 1289 * @return true, if any intent filters were changed due to this update 1290 */ updateMimeGroup(String packageName, String mimeGroup)1291 public boolean updateMimeGroup(String packageName, String mimeGroup) { 1292 F[] filters = mMimeGroupToFilter.get(mimeGroup); 1293 int n = filters != null ? filters.length : 0; 1294 1295 mIsUpdatingMimeGroup = true; 1296 boolean hasChanges = false; 1297 F filter; 1298 for (int i = 0; i < n && (filter = filters[i]) != null; i++) { 1299 if (isPackageForFilter(packageName, filter)) { 1300 hasChanges |= updateFilter(filter); 1301 } 1302 } 1303 mIsUpdatingMimeGroup = false; 1304 return hasChanges; 1305 } 1306 updateFilter(F f)1307 private boolean updateFilter(F f) { 1308 IntentFilter filter = getIntentFilter(f); 1309 List<String> oldTypes = filter.dataTypes(); 1310 removeFilter(f); 1311 addFilter(f); 1312 List<String> newTypes = filter.dataTypes(); 1313 return !equalLists(oldTypes, newTypes); 1314 } 1315 equalLists(List<String> first, List<String> second)1316 private boolean equalLists(List<String> first, List<String> second) { 1317 if (first == null) { 1318 return second == null; 1319 } else if (second == null) { 1320 return false; 1321 } 1322 1323 if (first.size() != second.size()) { 1324 return false; 1325 } 1326 1327 Collections.sort(first); 1328 Collections.sort(second); 1329 return first.equals(second); 1330 } 1331 applyMimeGroups(F f)1332 private void applyMimeGroups(F f) { 1333 IntentFilter filter = getIntentFilter(f); 1334 1335 for (int i = filter.countMimeGroups() - 1; i >= 0; i--) { 1336 List<String> mimeTypes = sPackageManagerInternal.getMimeGroup( 1337 f.first.getPackageName(), filter.getMimeGroup(i)); 1338 1339 for (int typeIndex = mimeTypes.size() - 1; typeIndex >= 0; typeIndex--) { 1340 String mimeType = mimeTypes.get(typeIndex); 1341 1342 try { 1343 filter.addDynamicDataType(mimeType); 1344 } catch (IntentFilter.MalformedMimeTypeException e) { 1345 if (DEBUG) { 1346 Slog.w(TAG, "Malformed mime type: " + mimeType, e); 1347 } 1348 } 1349 } 1350 } 1351 } 1352 } 1353 1354 private static class ActivityIntentResolver 1355 extends MimeGroupsAwareIntentResolver<Pair<ParsedActivity, ParsedIntentInfo>, ResolveInfo> { 1356 1357 // Default constructor ActivityIntentResolver()1358 ActivityIntentResolver() { 1359 } 1360 1361 // Copy constructor used in creating snapshots ActivityIntentResolver(ActivityIntentResolver orig)1362 ActivityIntentResolver(ActivityIntentResolver orig) { 1363 super(orig); 1364 mActivities.putAll(orig.mActivities); 1365 mFlags = orig.mFlags; 1366 } 1367 1368 @Override queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId)1369 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, 1370 boolean defaultOnly, int userId) { 1371 if (!sUserManager.exists(userId)) return null; 1372 mFlags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0); 1373 return super.queryIntent(intent, resolvedType, defaultOnly, userId); 1374 } 1375 queryIntent(Intent intent, String resolvedType, int flags, int userId)1376 List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags, 1377 int userId) { 1378 if (!sUserManager.exists(userId)) { 1379 return null; 1380 } 1381 mFlags = flags; 1382 return super.queryIntent(intent, resolvedType, 1383 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, 1384 userId); 1385 } 1386 queryIntentForPackage(Intent intent, String resolvedType, int flags, List<ParsedActivity> packageActivities, int userId)1387 List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType, 1388 int flags, List<ParsedActivity> packageActivities, int userId) { 1389 if (!sUserManager.exists(userId)) { 1390 return null; 1391 } 1392 if (packageActivities == null) { 1393 return Collections.emptyList(); 1394 } 1395 mFlags = flags; 1396 final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0; 1397 final int activitiesSize = packageActivities.size(); 1398 ArrayList<Pair<ParsedActivity, ParsedIntentInfo>[]> listCut = 1399 new ArrayList<>(activitiesSize); 1400 1401 List<ParsedIntentInfo> intentFilters; 1402 for (int i = 0; i < activitiesSize; ++i) { 1403 ParsedActivity activity = packageActivities.get(i); 1404 intentFilters = activity.getIntents(); 1405 if (!intentFilters.isEmpty()) { 1406 Pair<ParsedActivity, ParsedIntentInfo>[] array = newArray(intentFilters.size()); 1407 for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) { 1408 array[arrayIndex] = Pair.create(activity, intentFilters.get(arrayIndex)); 1409 } 1410 listCut.add(array); 1411 } 1412 } 1413 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId); 1414 } 1415 addActivity(ParsedActivity a, String type, List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents)1416 protected void addActivity(ParsedActivity a, String type, 1417 List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents) { 1418 mActivities.put(a.getComponentName(), a); 1419 if (DEBUG_SHOW_INFO) { 1420 Log.v(TAG, " " + type + ":"); 1421 Log.v(TAG, " Class=" + a.getName()); 1422 } 1423 final int intentsSize = a.getIntents().size(); 1424 for (int j = 0; j < intentsSize; j++) { 1425 ParsedIntentInfo intent = a.getIntents().get(j); 1426 if (newIntents != null && "activity".equals(type)) { 1427 newIntents.add(Pair.create(a, intent)); 1428 } 1429 if (DEBUG_SHOW_INFO) { 1430 Log.v(TAG, " IntentFilter:"); 1431 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); 1432 } 1433 if (!intent.debugCheck()) { 1434 Log.w(TAG, "==> For Activity " + a.getName()); 1435 } 1436 addFilter(Pair.create(a, intent)); 1437 } 1438 } 1439 removeActivity(ParsedActivity a, String type)1440 protected void removeActivity(ParsedActivity a, String type) { 1441 mActivities.remove(a.getComponentName()); 1442 if (DEBUG_SHOW_INFO) { 1443 Log.v(TAG, " " + type + ":"); 1444 Log.v(TAG, " Class=" + a.getName()); 1445 } 1446 final int intentsSize = a.getIntents().size(); 1447 for (int j = 0; j < intentsSize; j++) { 1448 ParsedIntentInfo intent = a.getIntents().get(j); 1449 if (DEBUG_SHOW_INFO) { 1450 Log.v(TAG, " IntentFilter:"); 1451 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); 1452 } 1453 removeFilter(Pair.create(a, intent)); 1454 } 1455 } 1456 1457 @Override allowFilterResult(Pair<ParsedActivity, ParsedIntentInfo> filter, List<ResolveInfo> dest)1458 protected boolean allowFilterResult(Pair<ParsedActivity, ParsedIntentInfo> filter, 1459 List<ResolveInfo> dest) { 1460 for (int i = dest.size() - 1; i >= 0; --i) { 1461 ActivityInfo destAi = dest.get(i).activityInfo; 1462 if (Objects.equals(destAi.name, filter.first.getName()) 1463 && Objects.equals(destAi.packageName, filter.first.getPackageName())) { 1464 return false; 1465 } 1466 } 1467 return true; 1468 } 1469 1470 @Override newArray(int size)1471 protected Pair<ParsedActivity, ParsedIntentInfo>[] newArray(int size) { 1472 //noinspection unchecked 1473 return (Pair<ParsedActivity, ParsedIntentInfo>[]) new Pair<?, ?>[size]; 1474 } 1475 1476 @Override isFilterStopped(Pair<ParsedActivity, ParsedIntentInfo> filter, int userId)1477 protected boolean isFilterStopped(Pair<ParsedActivity, ParsedIntentInfo> filter, int userId) { 1478 return ComponentResolver.isFilterStopped(filter, userId); 1479 } 1480 1481 @Override isPackageForFilter(String packageName, Pair<ParsedActivity, ParsedIntentInfo> info)1482 protected boolean isPackageForFilter(String packageName, 1483 Pair<ParsedActivity, ParsedIntentInfo> info) { 1484 return packageName.equals(info.first.getPackageName()); 1485 } 1486 log(String reason, ParsedIntentInfo info, int match, int userId)1487 private void log(String reason, ParsedIntentInfo info, int match, 1488 int userId) { 1489 Slog.w(TAG, reason 1490 + "; match: " 1491 + DebugUtils.flagsToString(IntentFilter.class, "MATCH_", match) 1492 + "; userId: " + userId 1493 + "; intent info: " + info); 1494 } 1495 1496 @Override newResult(Pair<ParsedActivity, ParsedIntentInfo> pair, int match, int userId)1497 protected ResolveInfo newResult(Pair<ParsedActivity, ParsedIntentInfo> pair, 1498 int match, int userId) { 1499 ParsedActivity activity = pair.first; 1500 ParsedIntentInfo info = pair.second; 1501 1502 if (!sUserManager.exists(userId)) { 1503 if (DEBUG) { 1504 log("User doesn't exist", info, match, userId); 1505 } 1506 return null; 1507 } 1508 1509 AndroidPackage pkg = sPackageManagerInternal.getPackage(activity.getPackageName()); 1510 if (pkg == null) { 1511 return null; 1512 } 1513 1514 if (!sPackageManagerInternal.isEnabledAndMatches(activity, mFlags, userId)) { 1515 if (DEBUG) { 1516 log("!PackageManagerInternal.isEnabledAndMatches; mFlags=" 1517 + DebugUtils.flagsToString(PackageManager.class, "MATCH_", mFlags), 1518 info, match, userId); 1519 } 1520 return null; 1521 } 1522 PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting( 1523 activity.getPackageName()); 1524 if (ps == null) { 1525 if (DEBUG) { 1526 log("info.activity.owner.mExtras == null", info, match, userId); 1527 } 1528 return null; 1529 } 1530 final PackageUserState userState = ps.readUserState(userId); 1531 ActivityInfo ai = PackageInfoUtils.generateActivityInfo(pkg, activity, mFlags, 1532 userState, userId, ps); 1533 if (ai == null) { 1534 if (DEBUG) { 1535 log("Failed to create ActivityInfo based on " + activity, info, match, 1536 userId); 1537 } 1538 return null; 1539 } 1540 final boolean matchExplicitlyVisibleOnly = 1541 (mFlags & PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY) != 0; 1542 final boolean matchVisibleToInstantApp = 1543 (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0; 1544 final boolean componentVisible = 1545 matchVisibleToInstantApp 1546 && info.isVisibleToInstantApp() 1547 && (!matchExplicitlyVisibleOnly || info.isExplicitlyVisibleToInstantApp()); 1548 final boolean matchInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0; 1549 // throw out filters that aren't visible to ephemeral apps 1550 if (matchVisibleToInstantApp && !(componentVisible || userState.instantApp)) { 1551 if (DEBUG) { 1552 log("Filter(s) not visible to ephemeral apps" 1553 + "; matchVisibleToInstantApp=" + matchVisibleToInstantApp 1554 + "; matchInstantApp=" + matchInstantApp 1555 + "; info.isVisibleToInstantApp()=" + info.isVisibleToInstantApp() 1556 + "; matchExplicitlyVisibleOnly=" + matchExplicitlyVisibleOnly 1557 + "; info.isExplicitlyVisibleToInstantApp()=" 1558 + info.isExplicitlyVisibleToInstantApp(), 1559 info, match, userId); 1560 } 1561 return null; 1562 } 1563 // throw out instant app filters if we're not explicitly requesting them 1564 if (!matchInstantApp && userState.instantApp) { 1565 if (DEBUG) { 1566 log("Instant app filter is not explicitly requested", info, match, userId); 1567 } 1568 return null; 1569 } 1570 // throw out instant app filters if updates are available; will trigger 1571 // instant app resolution 1572 if (userState.instantApp && ps.isUpdateAvailable()) { 1573 if (DEBUG) { 1574 log("Instant app update is available", info, match, userId); 1575 } 1576 return null; 1577 } 1578 final ResolveInfo res = new ResolveInfo(info.hasCategory(Intent.CATEGORY_BROWSABLE)); 1579 res.activityInfo = ai; 1580 if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) { 1581 res.filter = info; 1582 } 1583 res.handleAllWebDataURI = info.handleAllWebDataURI(); 1584 res.priority = info.getPriority(); 1585 // TODO(b/135203078): This field was unwritten and does nothing 1586 // res.preferredOrder = pkg.getPreferredOrder(); 1587 //System.out.println("Result: " + res.activityInfo.className + 1588 // " = " + res.priority); 1589 res.match = match; 1590 res.isDefault = info.isHasDefault(); 1591 res.labelRes = info.getLabelRes(); 1592 res.nonLocalizedLabel = info.getNonLocalizedLabel(); 1593 if (sPackageManagerInternal.userNeedsBadging(userId)) { 1594 res.noResourceId = true; 1595 } else { 1596 res.icon = info.getIcon(); 1597 } 1598 res.iconResourceId = info.getIcon(); 1599 res.system = res.activityInfo.applicationInfo.isSystemApp(); 1600 res.isInstantAppAvailable = userState.instantApp; 1601 return res; 1602 } 1603 1604 @Override sortResults(List<ResolveInfo> results)1605 protected void sortResults(List<ResolveInfo> results) { 1606 results.sort(RESOLVE_PRIORITY_SORTER); 1607 } 1608 1609 @Override dumpFilter(PrintWriter out, String prefix, Pair<ParsedActivity, ParsedIntentInfo> pair)1610 protected void dumpFilter(PrintWriter out, String prefix, 1611 Pair<ParsedActivity, ParsedIntentInfo> pair) { 1612 ParsedActivity activity = pair.first; 1613 ParsedIntentInfo filter = pair.second; 1614 1615 out.print(prefix); 1616 out.print(Integer.toHexString(System.identityHashCode(activity))); 1617 out.print(' '); 1618 ComponentName.printShortString(out, activity.getPackageName(), 1619 activity.getClassName()); 1620 out.print(" filter "); 1621 out.println(Integer.toHexString(System.identityHashCode(filter))); 1622 } 1623 1624 @Override filterToLabel(Pair<ParsedActivity, ParsedIntentInfo> filter)1625 protected Object filterToLabel(Pair<ParsedActivity, ParsedIntentInfo> filter) { 1626 return filter; 1627 } 1628 dumpFilterLabel(PrintWriter out, String prefix, Object label, int count)1629 protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) { 1630 @SuppressWarnings("unchecked") Pair<ParsedActivity, ParsedIntentInfo> pair = 1631 (Pair<ParsedActivity, ParsedIntentInfo>) label; 1632 out.print(prefix); 1633 out.print(Integer.toHexString(System.identityHashCode(pair.first))); 1634 out.print(' '); 1635 ComponentName.printShortString(out, pair.first.getPackageName(), 1636 pair.first.getClassName()); 1637 if (count > 1) { 1638 out.print(" ("); out.print(count); out.print(" filters)"); 1639 } 1640 out.println(); 1641 } 1642 1643 @Override getIntentFilter( @onNull Pair<ParsedActivity, ParsedIntentInfo> input)1644 protected IntentFilter getIntentFilter( 1645 @NonNull Pair<ParsedActivity, ParsedIntentInfo> input) { 1646 return input.second; 1647 } 1648 getResolveList(AndroidPackage pkg)1649 protected List<ParsedActivity> getResolveList(AndroidPackage pkg) { 1650 return pkg.getActivities(); 1651 } 1652 1653 // Keys are String (activity class name), values are Activity. This attribute is 1654 // protected because it is accessed directly from ComponentResolver. That works 1655 // even if the attribute is private, but fails for subclasses of 1656 // ActivityIntentResolver. 1657 protected final ArrayMap<ComponentName, ParsedActivity> mActivities = 1658 new ArrayMap<>(); 1659 private int mFlags; 1660 } 1661 1662 // Both receivers and activities share a class, but point to different get methods 1663 private static final class ReceiverIntentResolver extends ActivityIntentResolver { 1664 1665 // Default constructor ReceiverIntentResolver()1666 ReceiverIntentResolver() { 1667 } 1668 1669 // Copy constructor used in creating snapshots ReceiverIntentResolver(ReceiverIntentResolver orig)1670 ReceiverIntentResolver(ReceiverIntentResolver orig) { 1671 super(orig); 1672 } 1673 1674 @Override getResolveList(AndroidPackage pkg)1675 protected List<ParsedActivity> getResolveList(AndroidPackage pkg) { 1676 return pkg.getReceivers(); 1677 } 1678 } 1679 1680 private static final class ProviderIntentResolver 1681 extends MimeGroupsAwareIntentResolver<Pair<ParsedProvider, ParsedIntentInfo>, ResolveInfo> { 1682 // Default constructor ProviderIntentResolver()1683 ProviderIntentResolver() { 1684 } 1685 1686 // Copy constructor used in creating snapshots ProviderIntentResolver(ProviderIntentResolver orig)1687 ProviderIntentResolver(ProviderIntentResolver orig) { 1688 super(orig); 1689 mProviders.putAll(orig.mProviders); 1690 mFlags = orig.mFlags; 1691 } 1692 1693 @Override queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId)1694 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, 1695 boolean defaultOnly, int userId) { 1696 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0; 1697 return super.queryIntent(intent, resolvedType, defaultOnly, userId); 1698 } 1699 1700 @Nullable queryIntent(Intent intent, String resolvedType, int flags, int userId)1701 List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags, 1702 int userId) { 1703 if (!sUserManager.exists(userId)) { 1704 return null; 1705 } 1706 mFlags = flags; 1707 return super.queryIntent(intent, resolvedType, 1708 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, 1709 userId); 1710 } 1711 1712 @Nullable queryIntentForPackage(Intent intent, String resolvedType, int flags, List<ParsedProvider> packageProviders, int userId)1713 List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType, 1714 int flags, List<ParsedProvider> packageProviders, int userId) { 1715 if (!sUserManager.exists(userId)) { 1716 return null; 1717 } 1718 if (packageProviders == null) { 1719 return Collections.emptyList(); 1720 } 1721 mFlags = flags; 1722 final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0; 1723 final int providersSize = packageProviders.size(); 1724 ArrayList<Pair<ParsedProvider, ParsedIntentInfo>[]> listCut = 1725 new ArrayList<>(providersSize); 1726 1727 List<ParsedIntentInfo> intentFilters; 1728 for (int i = 0; i < providersSize; ++i) { 1729 ParsedProvider provider = packageProviders.get(i); 1730 intentFilters = provider.getIntents(); 1731 if (!intentFilters.isEmpty()) { 1732 Pair<ParsedProvider, ParsedIntentInfo>[] array = newArray(intentFilters.size()); 1733 for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) { 1734 array[arrayIndex] = Pair.create(provider, intentFilters.get(arrayIndex)); 1735 } 1736 listCut.add(array); 1737 } 1738 } 1739 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId); 1740 } 1741 addProvider(ParsedProvider p)1742 void addProvider(ParsedProvider p) { 1743 if (mProviders.containsKey(p.getComponentName())) { 1744 Slog.w(TAG, "Provider " + p.getComponentName() + " already defined; ignoring"); 1745 return; 1746 } 1747 1748 mProviders.put(p.getComponentName(), p); 1749 if (DEBUG_SHOW_INFO) { 1750 Log.v(TAG, " provider:"); 1751 Log.v(TAG, " Class=" + p.getName()); 1752 } 1753 final int intentsSize = p.getIntents().size(); 1754 int j; 1755 for (j = 0; j < intentsSize; j++) { 1756 ParsedIntentInfo intent = p.getIntents().get(j); 1757 if (DEBUG_SHOW_INFO) { 1758 Log.v(TAG, " IntentFilter:"); 1759 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); 1760 } 1761 if (!intent.debugCheck()) { 1762 Log.w(TAG, "==> For Provider " + p.getName()); 1763 } 1764 addFilter(Pair.create(p, intent)); 1765 } 1766 } 1767 removeProvider(ParsedProvider p)1768 void removeProvider(ParsedProvider p) { 1769 mProviders.remove(p.getComponentName()); 1770 if (DEBUG_SHOW_INFO) { 1771 Log.v(TAG, " provider:"); 1772 Log.v(TAG, " Class=" + p.getName()); 1773 } 1774 final int intentsSize = p.getIntents().size(); 1775 int j; 1776 for (j = 0; j < intentsSize; j++) { 1777 ParsedIntentInfo intent = p.getIntents().get(j); 1778 if (DEBUG_SHOW_INFO) { 1779 Log.v(TAG, " IntentFilter:"); 1780 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); 1781 } 1782 removeFilter(Pair.create(p, intent)); 1783 } 1784 } 1785 1786 @Override allowFilterResult(Pair<ParsedProvider, ParsedIntentInfo> filter, List<ResolveInfo> dest)1787 protected boolean allowFilterResult(Pair<ParsedProvider, ParsedIntentInfo> filter, 1788 List<ResolveInfo> dest) { 1789 for (int i = dest.size() - 1; i >= 0; i--) { 1790 ProviderInfo destPi = dest.get(i).providerInfo; 1791 if (Objects.equals(destPi.name, filter.first.getClassName()) 1792 && Objects.equals(destPi.packageName, filter.first.getPackageName())) { 1793 return false; 1794 } 1795 } 1796 return true; 1797 } 1798 1799 @Override newArray(int size)1800 protected Pair<ParsedProvider, ParsedIntentInfo>[] newArray(int size) { 1801 //noinspection unchecked 1802 return (Pair<ParsedProvider, ParsedIntentInfo>[]) new Pair<?, ?>[size]; 1803 } 1804 1805 @Override isFilterStopped(Pair<ParsedProvider, ParsedIntentInfo> filter, int userId)1806 protected boolean isFilterStopped(Pair<ParsedProvider, ParsedIntentInfo> filter, 1807 int userId) { 1808 return ComponentResolver.isFilterStopped(filter, userId); 1809 } 1810 1811 @Override isPackageForFilter(String packageName, Pair<ParsedProvider, ParsedIntentInfo> info)1812 protected boolean isPackageForFilter(String packageName, 1813 Pair<ParsedProvider, ParsedIntentInfo> info) { 1814 return packageName.equals(info.first.getPackageName()); 1815 } 1816 1817 @Override newResult(Pair<ParsedProvider, ParsedIntentInfo> pair, int match, int userId)1818 protected ResolveInfo newResult(Pair<ParsedProvider, ParsedIntentInfo> pair, 1819 int match, int userId) { 1820 if (!sUserManager.exists(userId)) { 1821 return null; 1822 } 1823 1824 ParsedProvider provider = pair.first; 1825 ParsedIntentInfo filter = pair.second; 1826 1827 AndroidPackage pkg = sPackageManagerInternal.getPackage(provider.getPackageName()); 1828 if (pkg == null) { 1829 return null; 1830 } 1831 1832 if (!sPackageManagerInternal.isEnabledAndMatches(provider, mFlags, userId)) { 1833 return null; 1834 } 1835 1836 PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting( 1837 provider.getPackageName()); 1838 if (ps == null) { 1839 return null; 1840 } 1841 final PackageUserState userState = ps.readUserState(userId); 1842 final boolean matchVisibleToInstantApp = (mFlags 1843 & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0; 1844 final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0; 1845 // throw out filters that aren't visible to instant applications 1846 if (matchVisibleToInstantApp 1847 && !(filter.isVisibleToInstantApp() || userState.instantApp)) { 1848 return null; 1849 } 1850 // throw out instant application filters if we're not explicitly requesting them 1851 if (!isInstantApp && userState.instantApp) { 1852 return null; 1853 } 1854 // throw out instant application filters if updates are available; will trigger 1855 // instant application resolution 1856 if (userState.instantApp && ps.isUpdateAvailable()) { 1857 return null; 1858 } 1859 final ApplicationInfo appInfo = PackageInfoUtils.generateApplicationInfo( 1860 pkg, mFlags, userState, userId, ps); 1861 if (appInfo == null) { 1862 return null; 1863 } 1864 ProviderInfo pi = PackageInfoUtils.generateProviderInfo(pkg, provider, mFlags, 1865 userState, appInfo, userId, ps); 1866 if (pi == null) { 1867 return null; 1868 } 1869 final ResolveInfo res = new ResolveInfo(); 1870 res.providerInfo = pi; 1871 if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) { 1872 res.filter = filter; 1873 } 1874 res.priority = filter.getPriority(); 1875 // TODO(b/135203078): This field was unwritten and does nothing 1876 // res.preferredOrder = pkg.getPreferredOrder(); 1877 res.match = match; 1878 res.isDefault = filter.isHasDefault(); 1879 res.labelRes = filter.getLabelRes(); 1880 res.nonLocalizedLabel = filter.getNonLocalizedLabel(); 1881 res.icon = filter.getIcon(); 1882 res.system = res.providerInfo.applicationInfo.isSystemApp(); 1883 return res; 1884 } 1885 1886 @Override sortResults(List<ResolveInfo> results)1887 protected void sortResults(List<ResolveInfo> results) { 1888 results.sort(RESOLVE_PRIORITY_SORTER); 1889 } 1890 1891 @Override dumpFilter(PrintWriter out, String prefix, Pair<ParsedProvider, ParsedIntentInfo> pair)1892 protected void dumpFilter(PrintWriter out, String prefix, 1893 Pair<ParsedProvider, ParsedIntentInfo> pair) { 1894 ParsedProvider provider = pair.first; 1895 ParsedIntentInfo filter = pair.second; 1896 1897 out.print(prefix); 1898 out.print(Integer.toHexString(System.identityHashCode(provider))); 1899 out.print(' '); 1900 ComponentName.printShortString(out, provider.getPackageName(), provider.getClassName()); 1901 out.print(" filter "); 1902 out.println(Integer.toHexString(System.identityHashCode(filter))); 1903 } 1904 1905 @Override filterToLabel(Pair<ParsedProvider, ParsedIntentInfo> filter)1906 protected Object filterToLabel(Pair<ParsedProvider, ParsedIntentInfo> filter) { 1907 return filter; 1908 } 1909 dumpFilterLabel(PrintWriter out, String prefix, Object label, int count)1910 protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) { 1911 @SuppressWarnings("unchecked") final Pair<ParsedProvider, ParsedIntentInfo> pair = 1912 (Pair<ParsedProvider, ParsedIntentInfo>) label; 1913 out.print(prefix); 1914 out.print(Integer.toHexString(System.identityHashCode(pair.first))); 1915 out.print(' '); 1916 ComponentName.printShortString(out, pair.first.getPackageName(), 1917 pair.first.getClassName()); 1918 if (count > 1) { 1919 out.print(" ("); 1920 out.print(count); 1921 out.print(" filters)"); 1922 } 1923 out.println(); 1924 } 1925 1926 @Override getIntentFilter( @onNull Pair<ParsedProvider, ParsedIntentInfo> input)1927 protected IntentFilter getIntentFilter( 1928 @NonNull Pair<ParsedProvider, ParsedIntentInfo> input) { 1929 return input.second; 1930 } 1931 1932 private final ArrayMap<ComponentName, ParsedProvider> mProviders = new ArrayMap<>(); 1933 private int mFlags; 1934 } 1935 1936 private static final class ServiceIntentResolver 1937 extends MimeGroupsAwareIntentResolver<Pair<ParsedService, ParsedIntentInfo>, ResolveInfo> { 1938 // Default constructor ServiceIntentResolver()1939 ServiceIntentResolver() { 1940 } 1941 1942 // Copy constructor used in creating snapshots ServiceIntentResolver(ServiceIntentResolver orig)1943 ServiceIntentResolver(ServiceIntentResolver orig) { 1944 copyFrom(orig); 1945 mServices.putAll(orig.mServices); 1946 mFlags = orig.mFlags; 1947 } 1948 1949 @Override queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId)1950 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, 1951 boolean defaultOnly, int userId) { 1952 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0; 1953 return super.queryIntent(intent, resolvedType, defaultOnly, userId); 1954 } 1955 queryIntent(Intent intent, String resolvedType, int flags, int userId)1956 List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags, 1957 int userId) { 1958 if (!sUserManager.exists(userId)) return null; 1959 mFlags = flags; 1960 return super.queryIntent(intent, resolvedType, 1961 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, 1962 userId); 1963 } 1964 queryIntentForPackage(Intent intent, String resolvedType, int flags, List<ParsedService> packageServices, int userId)1965 List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType, 1966 int flags, List<ParsedService> packageServices, int userId) { 1967 if (!sUserManager.exists(userId)) return null; 1968 if (packageServices == null) { 1969 return Collections.emptyList(); 1970 } 1971 mFlags = flags; 1972 final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0; 1973 final int servicesSize = packageServices.size(); 1974 ArrayList<Pair<ParsedService, ParsedIntentInfo>[]> listCut = 1975 new ArrayList<>(servicesSize); 1976 1977 List<ParsedIntentInfo> intentFilters; 1978 for (int i = 0; i < servicesSize; ++i) { 1979 ParsedService service = packageServices.get(i); 1980 intentFilters = service.getIntents(); 1981 if (intentFilters.size() > 0) { 1982 Pair<ParsedService, ParsedIntentInfo>[] array = newArray(intentFilters.size()); 1983 for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) { 1984 array[arrayIndex] = Pair.create(service, intentFilters.get(arrayIndex)); 1985 } 1986 listCut.add(array); 1987 } 1988 } 1989 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId); 1990 } 1991 addService(ParsedService s)1992 void addService(ParsedService s) { 1993 mServices.put(s.getComponentName(), s); 1994 if (DEBUG_SHOW_INFO) { 1995 Log.v(TAG, " service:"); 1996 Log.v(TAG, " Class=" + s.getName()); 1997 } 1998 final int intentsSize = s.getIntents().size(); 1999 int j; 2000 for (j = 0; j < intentsSize; j++) { 2001 ParsedIntentInfo intent = s.getIntents().get(j); 2002 if (DEBUG_SHOW_INFO) { 2003 Log.v(TAG, " IntentFilter:"); 2004 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); 2005 } 2006 if (!intent.debugCheck()) { 2007 Log.w(TAG, "==> For Service " + s.getName()); 2008 } 2009 addFilter(Pair.create(s, intent)); 2010 } 2011 } 2012 removeService(ParsedService s)2013 void removeService(ParsedService s) { 2014 mServices.remove(s.getComponentName()); 2015 if (DEBUG_SHOW_INFO) { 2016 Log.v(TAG, " service:"); 2017 Log.v(TAG, " Class=" + s.getName()); 2018 } 2019 final int intentsSize = s.getIntents().size(); 2020 int j; 2021 for (j = 0; j < intentsSize; j++) { 2022 ParsedIntentInfo intent = s.getIntents().get(j); 2023 if (DEBUG_SHOW_INFO) { 2024 Log.v(TAG, " IntentFilter:"); 2025 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); 2026 } 2027 removeFilter(Pair.create(s, intent)); 2028 } 2029 } 2030 2031 @Override allowFilterResult(Pair<ParsedService, ParsedIntentInfo> filter, List<ResolveInfo> dest)2032 protected boolean allowFilterResult(Pair<ParsedService, ParsedIntentInfo> filter, 2033 List<ResolveInfo> dest) { 2034 for (int i = dest.size() - 1; i >= 0; --i) { 2035 ServiceInfo destAi = dest.get(i).serviceInfo; 2036 if (Objects.equals(destAi.name, filter.first.getClassName()) 2037 && Objects.equals(destAi.packageName, filter.first.getPackageName())) { 2038 return false; 2039 } 2040 } 2041 return true; 2042 } 2043 2044 @Override newArray(int size)2045 protected Pair<ParsedService, ParsedIntentInfo>[] newArray(int size) { 2046 //noinspection unchecked 2047 return (Pair<ParsedService, ParsedIntentInfo>[]) new Pair<?, ?>[size]; 2048 } 2049 2050 @Override isFilterStopped(Pair<ParsedService, ParsedIntentInfo> filter, int userId)2051 protected boolean isFilterStopped(Pair<ParsedService, ParsedIntentInfo> filter, int userId) { 2052 return ComponentResolver.isFilterStopped(filter, userId); 2053 } 2054 2055 @Override isPackageForFilter(String packageName, Pair<ParsedService, ParsedIntentInfo> info)2056 protected boolean isPackageForFilter(String packageName, 2057 Pair<ParsedService, ParsedIntentInfo> info) { 2058 return packageName.equals(info.first.getPackageName()); 2059 } 2060 2061 @Override newResult(Pair<ParsedService, ParsedIntentInfo> pair, int match, int userId)2062 protected ResolveInfo newResult(Pair<ParsedService, ParsedIntentInfo> pair, int match, 2063 int userId) { 2064 if (!sUserManager.exists(userId)) return null; 2065 2066 ParsedService service = pair.first; 2067 ParsedIntentInfo filter = pair.second; 2068 2069 AndroidPackage pkg = sPackageManagerInternal.getPackage(service.getPackageName()); 2070 if (pkg == null) { 2071 return null; 2072 } 2073 2074 if (!sPackageManagerInternal.isEnabledAndMatches(service, mFlags, userId)) { 2075 return null; 2076 } 2077 2078 PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting( 2079 service.getPackageName()); 2080 if (ps == null) { 2081 return null; 2082 } 2083 final PackageUserState userState = ps.readUserState(userId); 2084 ServiceInfo si = PackageInfoUtils.generateServiceInfo(pkg, service, mFlags, 2085 userState, userId, ps); 2086 if (si == null) { 2087 return null; 2088 } 2089 final boolean matchVisibleToInstantApp = 2090 (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0; 2091 final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0; 2092 // throw out filters that aren't visible to ephemeral apps 2093 if (matchVisibleToInstantApp 2094 && !(filter.isVisibleToInstantApp() || userState.instantApp)) { 2095 return null; 2096 } 2097 // throw out ephemeral filters if we're not explicitly requesting them 2098 if (!isInstantApp && userState.instantApp) { 2099 return null; 2100 } 2101 // throw out instant app filters if updates are available; will trigger 2102 // instant app resolution 2103 if (userState.instantApp && ps.isUpdateAvailable()) { 2104 return null; 2105 } 2106 final ResolveInfo res = new ResolveInfo(); 2107 res.serviceInfo = si; 2108 if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) { 2109 res.filter = filter; 2110 } 2111 res.priority = filter.getPriority(); 2112 // TODO(b/135203078): This field was unwritten and does nothing 2113 // res.preferredOrder = pkg.getPreferredOrder(); 2114 res.match = match; 2115 res.isDefault = filter.isHasDefault(); 2116 res.labelRes = filter.getLabelRes(); 2117 res.nonLocalizedLabel = filter.getNonLocalizedLabel(); 2118 res.icon = filter.getIcon(); 2119 res.system = res.serviceInfo.applicationInfo.isSystemApp(); 2120 return res; 2121 } 2122 2123 @Override sortResults(List<ResolveInfo> results)2124 protected void sortResults(List<ResolveInfo> results) { 2125 results.sort(RESOLVE_PRIORITY_SORTER); 2126 } 2127 2128 @Override dumpFilter(PrintWriter out, String prefix, Pair<ParsedService, ParsedIntentInfo> pair)2129 protected void dumpFilter(PrintWriter out, String prefix, 2130 Pair<ParsedService, ParsedIntentInfo> pair) { 2131 ParsedService service = pair.first; 2132 ParsedIntentInfo filter = pair.second; 2133 2134 out.print(prefix); 2135 out.print(Integer.toHexString(System.identityHashCode(service))); 2136 out.print(' '); 2137 ComponentName.printShortString(out, service.getPackageName(), service.getClassName()); 2138 out.print(" filter "); 2139 out.print(Integer.toHexString(System.identityHashCode(filter))); 2140 if (service.getPermission() != null) { 2141 out.print(" permission "); out.println(service.getPermission()); 2142 } else { 2143 out.println(); 2144 } 2145 } 2146 2147 @Override filterToLabel(Pair<ParsedService, ParsedIntentInfo> filter)2148 protected Object filterToLabel(Pair<ParsedService, ParsedIntentInfo> filter) { 2149 return filter; 2150 } 2151 dumpFilterLabel(PrintWriter out, String prefix, Object label, int count)2152 protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) { 2153 @SuppressWarnings("unchecked") final Pair<ParsedService, ParsedIntentInfo> pair = 2154 (Pair<ParsedService, ParsedIntentInfo>) label; 2155 out.print(prefix); 2156 out.print(Integer.toHexString(System.identityHashCode(pair.first))); 2157 out.print(' '); 2158 ComponentName.printShortString(out, pair.first.getPackageName(), 2159 pair.first.getClassName()); 2160 if (count > 1) { 2161 out.print(" ("); out.print(count); out.print(" filters)"); 2162 } 2163 out.println(); 2164 } 2165 2166 @Override getIntentFilter( @onNull Pair<ParsedService, ParsedIntentInfo> input)2167 protected IntentFilter getIntentFilter( 2168 @NonNull Pair<ParsedService, ParsedIntentInfo> input) { 2169 return input.second; 2170 } 2171 2172 // Keys are String (activity class name), values are Activity. 2173 private final ArrayMap<ComponentName, ParsedService> mServices = new ArrayMap<>(); 2174 private int mFlags; 2175 } 2176 2177 static final class InstantAppIntentResolver 2178 extends IntentResolver<AuxiliaryResolveInfo.AuxiliaryFilter, 2179 AuxiliaryResolveInfo.AuxiliaryFilter> { 2180 /** 2181 * The result that has the highest defined order. Ordering applies on a 2182 * per-package basis. Mapping is from package name to Pair of order and 2183 * EphemeralResolveInfo. 2184 * <p> 2185 * NOTE: This is implemented as a field variable for convenience and efficiency. 2186 * By having a field variable, we're able to track filter ordering as soon as 2187 * a non-zero order is defined. Otherwise, multiple loops across the result set 2188 * would be needed to apply ordering. If the intent resolver becomes re-entrant, 2189 * this needs to be contained entirely within {@link #filterResults}. 2190 */ 2191 final ArrayMap<String, Pair<Integer, InstantAppResolveInfo>> mOrderResult = 2192 new ArrayMap<>(); 2193 2194 @Override newArray(int size)2195 protected AuxiliaryResolveInfo.AuxiliaryFilter[] newArray(int size) { 2196 return new AuxiliaryResolveInfo.AuxiliaryFilter[size]; 2197 } 2198 2199 @Override isPackageForFilter(String packageName, AuxiliaryResolveInfo.AuxiliaryFilter responseObj)2200 protected boolean isPackageForFilter(String packageName, 2201 AuxiliaryResolveInfo.AuxiliaryFilter responseObj) { 2202 return true; 2203 } 2204 2205 @Override newResult( AuxiliaryResolveInfo.AuxiliaryFilter responseObj, int match, int userId)2206 protected AuxiliaryResolveInfo.AuxiliaryFilter newResult( 2207 AuxiliaryResolveInfo.AuxiliaryFilter responseObj, int match, int userId) { 2208 if (!sUserManager.exists(userId)) { 2209 return null; 2210 } 2211 final String packageName = responseObj.resolveInfo.getPackageName(); 2212 final Integer order = responseObj.getOrder(); 2213 final Pair<Integer, InstantAppResolveInfo> lastOrderResult = 2214 mOrderResult.get(packageName); 2215 // ordering is enabled and this item's order isn't high enough 2216 if (lastOrderResult != null && lastOrderResult.first >= order) { 2217 return null; 2218 } 2219 final InstantAppResolveInfo res = responseObj.resolveInfo; 2220 if (order > 0) { 2221 // non-zero order, enable ordering 2222 mOrderResult.put(packageName, new Pair<>(order, res)); 2223 } 2224 return responseObj; 2225 } 2226 2227 @Override filterResults(List<AuxiliaryResolveInfo.AuxiliaryFilter> results)2228 protected void filterResults(List<AuxiliaryResolveInfo.AuxiliaryFilter> results) { 2229 // only do work if ordering is enabled [most of the time it won't be] 2230 if (mOrderResult.size() == 0) { 2231 return; 2232 } 2233 int resultSize = results.size(); 2234 for (int i = 0; i < resultSize; i++) { 2235 final InstantAppResolveInfo info = results.get(i).resolveInfo; 2236 final String packageName = info.getPackageName(); 2237 final Pair<Integer, InstantAppResolveInfo> savedInfo = 2238 mOrderResult.get(packageName); 2239 if (savedInfo == null) { 2240 // package doesn't having ordering 2241 continue; 2242 } 2243 if (savedInfo.second == info) { 2244 // circled back to the highest ordered item; remove from order list 2245 mOrderResult.remove(packageName); 2246 if (mOrderResult.size() == 0) { 2247 // no more ordered items 2248 break; 2249 } 2250 continue; 2251 } 2252 // item has a worse order, remove it from the result list 2253 results.remove(i); 2254 resultSize--; 2255 i--; 2256 } 2257 } 2258 2259 @Override getIntentFilter( @onNull AuxiliaryResolveInfo.AuxiliaryFilter input)2260 protected IntentFilter getIntentFilter( 2261 @NonNull AuxiliaryResolveInfo.AuxiliaryFilter input) { 2262 return input; 2263 } 2264 } 2265 isFilterStopped(Pair<? extends ParsedComponent, ParsedIntentInfo> pair, int userId)2266 private static boolean isFilterStopped(Pair<? extends ParsedComponent, ParsedIntentInfo> pair, 2267 int userId) { 2268 if (!sUserManager.exists(userId)) { 2269 return true; 2270 } 2271 2272 AndroidPackage pkg = sPackageManagerInternal.getPackage(pair.first.getPackageName()); 2273 if (pkg == null) { 2274 return false; 2275 } 2276 2277 PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting( 2278 pair.first.getPackageName()); 2279 if (ps == null) { 2280 return false; 2281 } 2282 2283 // System apps are never considered stopped for purposes of 2284 // filtering, because there may be no way for the user to 2285 // actually re-launch them. 2286 return !ps.isSystem() && ps.getStopped(userId); 2287 } 2288 2289 /** Generic to create an {@link Iterator} for a data type */ 2290 static class IterGenerator<E> { generate(ParsedIntentInfo info)2291 public Iterator<E> generate(ParsedIntentInfo info) { 2292 return null; 2293 } 2294 } 2295 2296 /** Create an {@link Iterator} for intent actions */ 2297 static class ActionIterGenerator extends IterGenerator<String> { 2298 @Override generate(ParsedIntentInfo info)2299 public Iterator<String> generate(ParsedIntentInfo info) { 2300 return info.actionsIterator(); 2301 } 2302 } 2303 2304 /** Create an {@link Iterator} for intent categories */ 2305 static class CategoriesIterGenerator extends IterGenerator<String> { 2306 @Override generate(ParsedIntentInfo info)2307 public Iterator<String> generate(ParsedIntentInfo info) { 2308 return info.categoriesIterator(); 2309 } 2310 } 2311 2312 /** Create an {@link Iterator} for intent schemes */ 2313 static class SchemesIterGenerator extends IterGenerator<String> { 2314 @Override generate(ParsedIntentInfo info)2315 public Iterator<String> generate(ParsedIntentInfo info) { 2316 return info.schemesIterator(); 2317 } 2318 } 2319 2320 /** Create an {@link Iterator} for intent authorities */ 2321 static class AuthoritiesIterGenerator extends IterGenerator<IntentFilter.AuthorityEntry> { 2322 @Override generate(ParsedIntentInfo info)2323 public Iterator<IntentFilter.AuthorityEntry> generate(ParsedIntentInfo info) { 2324 return info.authoritiesIterator(); 2325 } 2326 } 2327 2328 /** 2329 * Removes MIME type from the group, by delegating to IntentResolvers 2330 * @return true if any intent filters were changed due to this update 2331 */ updateMimeGroup(String packageName, String group)2332 boolean updateMimeGroup(String packageName, String group) { 2333 boolean hasChanges = false; 2334 synchronized (mLock) { 2335 hasChanges |= mActivities.updateMimeGroup(packageName, group); 2336 hasChanges |= mProviders.updateMimeGroup(packageName, group); 2337 hasChanges |= mReceivers.updateMimeGroup(packageName, group); 2338 hasChanges |= mServices.updateMimeGroup(packageName, group); 2339 if (hasChanges) { 2340 onChanged(); 2341 } 2342 } 2343 return hasChanges; 2344 } 2345 } 2346