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