1 package org.robolectric.shadows; 2 3 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 4 import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID; 5 import static android.content.pm.PackageManager.GET_ACTIVITIES; 6 import static android.content.pm.PackageManager.GET_CONFIGURATIONS; 7 import static android.content.pm.PackageManager.GET_GIDS; 8 import static android.content.pm.PackageManager.GET_INSTRUMENTATION; 9 import static android.content.pm.PackageManager.GET_INTENT_FILTERS; 10 import static android.content.pm.PackageManager.GET_META_DATA; 11 import static android.content.pm.PackageManager.GET_PERMISSIONS; 12 import static android.content.pm.PackageManager.GET_PROVIDERS; 13 import static android.content.pm.PackageManager.GET_RECEIVERS; 14 import static android.content.pm.PackageManager.GET_RESOLVED_FILTER; 15 import static android.content.pm.PackageManager.GET_SERVICES; 16 import static android.content.pm.PackageManager.GET_SHARED_LIBRARY_FILES; 17 import static android.content.pm.PackageManager.GET_SIGNATURES; 18 import static android.content.pm.PackageManager.GET_URI_PERMISSION_PATTERNS; 19 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; 20 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; 21 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS; 22 import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS; 23 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; 24 import static android.content.pm.PackageManager.SIGNATURE_FIRST_NOT_SIGNED; 25 import static android.content.pm.PackageManager.SIGNATURE_MATCH; 26 import static android.content.pm.PackageManager.SIGNATURE_NEITHER_SIGNED; 27 import static android.content.pm.PackageManager.SIGNATURE_NO_MATCH; 28 import static android.content.pm.PackageManager.SIGNATURE_SECOND_NOT_SIGNED; 29 import static android.content.pm.PackageManager.VERIFICATION_ALLOW; 30 import static android.os.Build.VERSION_CODES.N; 31 import static android.os.Build.VERSION_CODES.TIRAMISU; 32 import static com.google.common.collect.ImmutableList.toImmutableList; 33 import static java.util.Arrays.asList; 34 import static org.robolectric.util.reflector.Reflector.reflector; 35 36 import android.Manifest; 37 import android.Manifest.permission; 38 import android.Manifest.permission_group; 39 import android.annotation.UserIdInt; 40 import android.app.Application; 41 import android.content.BroadcastReceiver; 42 import android.content.ComponentName; 43 import android.content.Context; 44 import android.content.Intent; 45 import android.content.IntentFilter; 46 import android.content.IntentSender; 47 import android.content.pm.ActivityInfo; 48 import android.content.pm.ApplicationInfo; 49 import android.content.pm.ComponentInfo; 50 import android.content.pm.FeatureInfo; 51 import android.content.pm.IPackageDataObserver; 52 import android.content.pm.IPackageDeleteObserver; 53 import android.content.pm.InstallSourceInfo; 54 import android.content.pm.ModuleInfo; 55 import android.content.pm.PackageInfo; 56 import android.content.pm.PackageManager; 57 import android.content.pm.PackageParser; 58 import android.content.pm.PackageParser.Component; 59 import android.content.pm.PackageParser.IntentInfo; 60 import android.content.pm.PackageParser.Package; 61 import android.content.pm.PackageParser.PermissionGroup; 62 import android.content.pm.PackageStats; 63 import android.content.pm.PermissionGroupInfo; 64 import android.content.pm.PermissionInfo; 65 import android.content.pm.ProviderInfo; 66 import android.content.pm.ResolveInfo; 67 import android.content.pm.ServiceInfo; 68 import android.content.pm.Signature; 69 import android.content.pm.SigningInfo; 70 import android.content.pm.pkg.FrameworkPackageUserState; 71 import android.content.res.Resources; 72 import android.graphics.drawable.Drawable; 73 import android.net.Uri; 74 import android.os.Binder; 75 import android.os.PersistableBundle; 76 import android.os.Process; 77 import android.os.RemoteException; 78 import android.os.UserHandle; 79 import android.util.Log; 80 import android.util.Pair; 81 import com.google.common.base.Function; 82 import com.google.common.base.Preconditions; 83 import com.google.common.collect.HashMultimap; 84 import com.google.common.collect.ImmutableList; 85 import com.google.common.collect.ImmutableMap; 86 import com.google.common.collect.Multimap; 87 import com.google.errorprone.annotations.InlineMe; 88 import java.lang.reflect.Array; 89 import java.util.ArrayList; 90 import java.util.Arrays; 91 import java.util.Collections; 92 import java.util.Comparator; 93 import java.util.HashMap; 94 import java.util.HashSet; 95 import java.util.Iterator; 96 import java.util.LinkedHashMap; 97 import java.util.List; 98 import java.util.Map; 99 import java.util.Map.Entry; 100 import java.util.Set; 101 import java.util.SortedMap; 102 import java.util.TreeMap; 103 import java.util.concurrent.ConcurrentHashMap; 104 import java.util.concurrent.CopyOnWriteArraySet; 105 import java.util.function.BiConsumer; 106 import javax.annotation.Nullable; 107 import javax.annotation.concurrent.GuardedBy; 108 import org.robolectric.RuntimeEnvironment; 109 import org.robolectric.annotation.Implementation; 110 import org.robolectric.annotation.Implements; 111 import org.robolectric.annotation.RealObject; 112 import org.robolectric.annotation.Resetter; 113 import org.robolectric.shadows.ShadowPackageParser._PackageParser_; 114 import org.robolectric.util.reflector.Direct; 115 import org.robolectric.util.reflector.ForType; 116 117 @SuppressWarnings("NewApi") 118 @Implements(PackageManager.class) 119 public class ShadowPackageManager { 120 static final String TAG = "PackageManager"; 121 122 @RealObject PackageManager realPackageManager; 123 124 // The big-lock to control concurrency in this class. 125 // Note: not all APIs in this class have been made thread safe yet. 126 static final Object lock = new Object(); 127 static Map<String, Boolean> permissionRationaleMap = new HashMap<>(); 128 static List<FeatureInfo> systemAvailableFeatures = new ArrayList<>(); 129 static final List<String> systemSharedLibraryNames = new ArrayList<>(); 130 131 @GuardedBy("lock") 132 static final Map<String, PackageInfo> packageInfos = new LinkedHashMap<>(); 133 134 @GuardedBy("lock") 135 static final Map<String, ModuleInfo> moduleInfos = new LinkedHashMap<>(); 136 137 static final Set<Object> permissionListeners = new CopyOnWriteArraySet<>(); 138 139 // Those maps contain filter for components. If component exists but doesn't have filters, 140 // it will have an entry in the map with an empty list. 141 static final SortedMap<ComponentName, List<IntentFilter>> activityFilters = new TreeMap<>(); 142 static final SortedMap<ComponentName, List<IntentFilter>> serviceFilters = new TreeMap<>(); 143 static final SortedMap<ComponentName, List<IntentFilter>> providerFilters = new TreeMap<>(); 144 static final SortedMap<ComponentName, List<IntentFilter>> receiverFilters = new TreeMap<>(); 145 146 private static Map<String, PackageInfo> packageArchiveInfo = new HashMap<>(); 147 static final Map<String, PackageStats> packageStatsMap = new HashMap<>(); 148 static final Map<String, String> packageInstallerMap = new HashMap<>(); 149 static final Map<String, Object> packageInstallSourceInfoMap = new HashMap<>(); 150 static final Map<Integer, String[]> packagesForUid = new HashMap<>(); 151 static final Map<String, Integer> uidForPackage = new HashMap<>(); 152 static final Map<Integer, String> namesForUid = new HashMap<>(); 153 static final Map<Integer, Integer> verificationResults = new HashMap<>(); 154 155 @GuardedBy("lock") 156 static final Map<Integer, Long> verificationTimeoutExtension = new HashMap<>(); 157 158 @GuardedBy("lock") 159 static final Map<Integer, Integer> verificationCodeAtTimeoutExtension = new HashMap<>(); 160 161 static final Map<String, String> currentToCanonicalNames = new HashMap<>(); 162 static final Map<String, String> canonicalToCurrentNames = new HashMap<>(); 163 static final Map<ComponentName, ComponentState> componentList = new LinkedHashMap<>(); 164 static final Map<ComponentName, Drawable> drawableList = new LinkedHashMap<>(); 165 static final Map<String, Drawable> applicationIcons = new HashMap<>(); 166 static final Map<String, Drawable> unbadgedApplicationIcons = new HashMap<>(); 167 static final Map<String, Boolean> systemFeatureList = 168 new LinkedHashMap<>(SystemFeatureListInitializer.getSystemFeatures()); 169 static final SortedMap<ComponentName, List<IntentFilter>> preferredActivities = new TreeMap<>(); 170 static final SortedMap<ComponentName, List<IntentFilter>> persistentPreferredActivities = 171 new TreeMap<>(); 172 static final Map<Pair<String, Integer>, Drawable> drawables = new LinkedHashMap<>(); 173 174 /** 175 * Map of package names to an inner map where the key is the resource id which fetches its 176 * corresponding text. 177 */ 178 static final Map<String, Map<Integer, String>> stringResources = new HashMap<>(); 179 180 static final Map<String, Integer> applicationEnabledSettingMap = new HashMap<>(); 181 static Map<String, PermissionInfo> extraPermissions = new HashMap<>(); 182 static Map<String, PermissionGroupInfo> permissionGroups = new HashMap<>(); 183 184 /** 185 * Map of package names to an inner map where the key is the permission and the integer represents 186 * the permission flags set for that particular permission 187 */ 188 static Map<String, Map<String, Integer>> permissionFlags = new HashMap<>(); 189 190 public static Map<String, Resources> resources = new HashMap<>(); 191 static final Map<Intent, List<ResolveInfo>> resolveInfoForIntent = 192 new TreeMap<>(new IntentComparator()); 193 194 @GuardedBy("lock") 195 static Set<String> deletedPackages = new HashSet<>(); 196 197 static Map<String, IPackageDeleteObserver> pendingDeleteCallbacks = new HashMap<>(); 198 static Set<String> hiddenPackages = new HashSet<>(); 199 static Multimap<Integer, String> sequenceNumberChangedPackagesMap = HashMultimap.create(); 200 static boolean canRequestPackageInstalls = false; 201 static boolean safeMode = false; 202 static boolean whitelisted = false; 203 boolean shouldShowActivityChooser = false; 204 static final Map<String, Integer> distractingPackageRestrictions = new ConcurrentHashMap<>(); 205 206 static final String AOSP_PLATFORM_PERMISSION_GROUP_PREFIX = "android.permission-group."; 207 static final String AOSP_PLATFORM_PERMISSION_PREFIX = "android.permission."; 208 209 /** 210 * Limited set of platform permission groups and their metadata as defined in API level 23. 211 * 212 * <p>The source of truth for the list of platform permission groups and their metadata is the 213 * core framework AndroidManifest.xml file in the Android SDK. For the latest version see: 214 * https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/res/AndroidManifest.xml 215 * Note that new groups may be added and changes to existing groups may be made in each existing 216 * and future versions. 217 */ 218 static final ImmutableMap<String, PermissionGroupInfo> AOSP_PLATFORM_PERMISSION_GROUPS = 219 ImmutableMap.of( 220 permission_group.CALENDAR, 221 createPermissionGroupInfo( 222 permission_group.CALENDAR, "Calendar", "access your calendar", 200), 223 permission_group.CONTACTS, 224 createPermissionGroupInfo( 225 permission_group.CONTACTS, "Contacts", "access your contacts", 100)); 226 227 /** 228 * Limited set of platform permissions and their metadata as defined in API level 23. 229 * 230 * <p>The source of truth for the list of platform permissions and their metadata is the core 231 * framework AndroidManifest.xml file in the Android SDK. For the latest version see: 232 * https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/res/AndroidManifest.xml 233 * Note that new permissions may be added and changes to existing permissions may be made in each 234 * existing and future versions. 235 * 236 * <p>The mapping of permissions to groups was removed from the core framework AndroidManifest.xml 237 * file. The current source of truth is in the Permission mainline module: 238 * https://cs.android.com/android/platform/superproject/main/+/main:packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt 239 */ 240 static final ImmutableMap<String, PermissionInfo> AOSP_PLATFORM_PERMISSIONS = 241 ImmutableMap.of( 242 permission.READ_CALENDAR, 243 createPermissionInfo( 244 permission.READ_CALENDAR, 245 "read calendar events plus confidential information", 246 "Allows the app to read all calendar events stored on your phone, including those of" 247 + " friends or co-workers. This may allow the app to share or save your calendar" 248 + " data, regardless of confidentiality or sensitivity.", 249 PermissionInfo.PROTECTION_DANGEROUS, 250 permission_group.CALENDAR), 251 permission.WRITE_CALENDAR, 252 createPermissionInfo( 253 permission.WRITE_CALENDAR, 254 "add or modify calendar events and send email to guests without owners\' knowledge", 255 "Allows the app to add, remove, change events that you can modify on your phone," 256 + " including those of friends or co-workers. This may allow the app to send" 257 + " messages that appear to come from calendar owners, or modify events without" 258 + " the owners\' knowledge.", 259 PermissionInfo.PROTECTION_DANGEROUS, 260 permission_group.CALENDAR), 261 permission.GET_ACCOUNTS, 262 createPermissionInfo( 263 permission.GET_ACCOUNTS, 264 "find accounts on the device", 265 "Allows the app to get the list of accounts known by the phone. This may include any" 266 + " accounts created by applications you have installed.", 267 PermissionInfo.PROTECTION_DANGEROUS, 268 permission_group.CONTACTS), 269 permission.READ_CONTACTS, 270 createPermissionInfo( 271 permission.READ_CONTACTS, 272 "read your contacts", 273 "Allows the app to read data about your contacts stored on your phone, including the" 274 + " frequency with which you\'ve called, emailed, or communicated in other ways" 275 + " with specific individuals. This permission allows apps to save your contact" 276 + " data, and malicious apps may share contact data without your knowledge.", 277 PermissionInfo.PROTECTION_DANGEROUS, 278 permission_group.CONTACTS), 279 permission.WRITE_CONTACTS, 280 createPermissionInfo( 281 permission.WRITE_CONTACTS, 282 "modify your contacts", 283 "Allows the app to modify the data about your contacts stored on your phone," 284 + " including the frequency with which you\'ve called, emailed, or communicated" 285 + " in other ways with specific contacts. This permission allows apps to delete" 286 + " contact data.", 287 PermissionInfo.PROTECTION_DANGEROUS, 288 permission_group.CONTACTS)); 289 createPermissionGroupInfo( String name, String label, String description, int priority)290 private static PermissionGroupInfo createPermissionGroupInfo( 291 String name, String label, String description, int priority) { 292 PermissionGroupInfo permissionGroupInfo = new PermissionGroupInfo(); 293 permissionGroupInfo.name = name; 294 permissionGroupInfo.nonLocalizedDescription = description; 295 permissionGroupInfo.nonLocalizedLabel = label; 296 permissionGroupInfo.priority = priority; 297 return permissionGroupInfo; 298 } 299 createPermissionInfo( String name, String label, String description, int protectionLevel, String group)300 private static PermissionInfo createPermissionInfo( 301 String name, String label, String description, int protectionLevel, String group) { 302 PermissionInfo permissionInfo = new PermissionInfo(); 303 permissionInfo.group = group; 304 permissionInfo.name = name; 305 permissionInfo.nonLocalizedDescription = description; 306 permissionInfo.nonLocalizedLabel = label; 307 permissionInfo.protectionLevel = protectionLevel; 308 return permissionInfo; 309 } 310 311 /** 312 * Makes sure that given activity exists. 313 * 314 * <p>If the activity doesn't exist yet, it will be created with {@code applicationInfo} set to an 315 * existing application, or if it doesn't exist, a new package will be created. 316 * 317 * @return existing or newly created activity info. 318 */ addActivityIfNotPresent(ComponentName componentName)319 public ActivityInfo addActivityIfNotPresent(ComponentName componentName) { 320 ActivityInfo activityInfo = updateName(componentName, new ActivityInfo()); 321 activityInfo.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED; 322 return addComponent( 323 activityFilters, p -> p.activities, (p, a) -> p.activities = a, activityInfo, false); 324 } 325 326 /** 327 * Makes sure that given service exists. 328 * 329 * <p>If the service doesn't exist yet, it will be created with {@code applicationInfo} set to an 330 * existing application, or if it doesn't exist, a new package will be created. 331 * 332 * @return existing or newly created service info. 333 */ addServiceIfNotPresent(ComponentName componentName)334 public ServiceInfo addServiceIfNotPresent(ComponentName componentName) { 335 return addComponent( 336 serviceFilters, 337 p -> p.services, 338 (p, a) -> p.services = a, 339 updateName(componentName, new ServiceInfo()), 340 false); 341 } 342 343 /** 344 * Makes sure that given receiver exists. 345 * 346 * <p>If the receiver doesn't exist yet, it will be created with {@code applicationInfo} set to an 347 * existing application, or if it doesn't exist, a new package will be created. 348 * 349 * @return existing or newly created receiver info. 350 */ addReceiverIfNotPresent(ComponentName componentName)351 public ActivityInfo addReceiverIfNotPresent(ComponentName componentName) { 352 return addComponent( 353 receiverFilters, 354 p -> p.receivers, 355 (p, a) -> p.receivers = a, 356 updateName(componentName, new ActivityInfo()), 357 false); 358 } 359 360 /** 361 * Makes sure that given provider exists. 362 * 363 * <p>If the provider doesn't exist yet, it will be created with {@code applicationInfo} set to an 364 * existing application, or if it doesn't exist, a new package will be created. 365 * 366 * @return existing or newly created provider info. 367 */ addProviderIfNotPresent(ComponentName componentName)368 public ProviderInfo addProviderIfNotPresent(ComponentName componentName) { 369 return addComponent( 370 providerFilters, 371 p -> p.providers, 372 (p, a) -> p.providers = a, 373 updateName(componentName, new ProviderInfo()), 374 false); 375 } 376 updateName(ComponentName name, C component)377 private <C extends ComponentInfo> C updateName(ComponentName name, C component) { 378 component.name = name.getClassName(); 379 component.packageName = name.getPackageName(); 380 if (component.applicationInfo != null) { 381 component.applicationInfo.packageName = component.packageName; 382 } 383 return component; 384 } 385 386 /** 387 * Adds or updates given activity in the system. 388 * 389 * <p>If activity with the same {@link ComponentInfo#name} and {@code ComponentInfo#packageName} 390 * exists it will be updated. Its {@link ComponentInfo#applicationInfo} is always set to {@link 391 * ApplicationInfo} already existing in the system, but if no application exists a new one will be 392 * created using {@link ComponentInfo#applicationInfo} in this component. 393 */ addOrUpdateActivity(ActivityInfo activityInfo)394 public void addOrUpdateActivity(ActivityInfo activityInfo) { 395 addComponent( 396 activityFilters, 397 p -> p.activities, 398 (p, a) -> p.activities = a, 399 new ActivityInfo(activityInfo), 400 true); 401 } 402 403 /** 404 * Adds or updates given service in the system. 405 * 406 * <p>If service with the same {@link ComponentInfo#name} and {@code ComponentInfo#packageName} 407 * exists it will be updated. Its {@link ComponentInfo#applicationInfo} is always set to {@link 408 * ApplicationInfo} already existing in the system, but if no application exists a new one will be 409 * created using {@link ComponentInfo#applicationInfo} in this component. 410 */ addOrUpdateService(ServiceInfo serviceInfo)411 public void addOrUpdateService(ServiceInfo serviceInfo) { 412 addComponent( 413 serviceFilters, 414 p -> p.services, 415 (p, a) -> p.services = a, 416 new ServiceInfo(serviceInfo), 417 true); 418 } 419 420 /** 421 * Adds or updates given broadcast receiver in the system. 422 * 423 * <p>If broadcast receiver with the same {@link ComponentInfo#name} and {@code 424 * ComponentInfo#packageName} exists it will be updated. Its {@link ComponentInfo#applicationInfo} 425 * is always set to {@link ApplicationInfo} already existing in the system, but if no application 426 * exists a new one will be created using {@link ComponentInfo#applicationInfo} in this component. 427 */ addOrUpdateReceiver(ActivityInfo receiverInfo)428 public void addOrUpdateReceiver(ActivityInfo receiverInfo) { 429 addComponent( 430 receiverFilters, 431 p -> p.receivers, 432 (p, a) -> p.receivers = a, 433 new ActivityInfo(receiverInfo), 434 true); 435 } 436 437 /** 438 * Adds or updates given content provider in the system. 439 * 440 * <p>If content provider with the same {@link ComponentInfo#name} and {@code 441 * ComponentInfo#packageName} exists it will be updated. Its {@link ComponentInfo#applicationInfo} 442 * is always set to {@link ApplicationInfo} already existing in the system, but if no application 443 * exists a new one will be created using {@link ComponentInfo#applicationInfo} in this component. 444 */ addOrUpdateProvider(ProviderInfo providerInfo)445 public void addOrUpdateProvider(ProviderInfo providerInfo) { 446 addComponent( 447 providerFilters, 448 p -> p.providers, 449 (p, a) -> p.providers = a, 450 new ProviderInfo(providerInfo), 451 true); 452 } 453 454 /** 455 * Removes activity from the package manager. 456 * 457 * @return the removed component or {@code null} if no such component existed. 458 */ 459 @Nullable removeActivity(ComponentName componentName)460 public ActivityInfo removeActivity(ComponentName componentName) { 461 return removeComponent( 462 componentName, activityFilters, p -> p.activities, (p, a) -> p.activities = a); 463 } 464 465 /** 466 * Removes service from the package manager. 467 * 468 * @return the removed component or {@code null} if no such component existed. 469 */ 470 @Nullable removeService(ComponentName componentName)471 public ServiceInfo removeService(ComponentName componentName) { 472 return removeComponent( 473 componentName, serviceFilters, p -> p.services, (p, a) -> p.services = a); 474 } 475 476 /** 477 * Removes content provider from the package manager. 478 * 479 * @return the removed component or {@code null} if no such component existed. 480 */ 481 @Nullable removeProvider(ComponentName componentName)482 public ProviderInfo removeProvider(ComponentName componentName) { 483 return removeComponent( 484 componentName, providerFilters, p -> p.providers, (p, a) -> p.providers = a); 485 } 486 487 /** 488 * Removes broadcast receiver from the package manager. 489 * 490 * @return the removed component or {@code null} if no such component existed. 491 */ 492 @Nullable removeReceiver(ComponentName componentName)493 public ActivityInfo removeReceiver(ComponentName componentName) { 494 return removeComponent( 495 componentName, receiverFilters, p -> p.receivers, (p, a) -> p.receivers = a); 496 } 497 addComponent( SortedMap<ComponentName, List<IntentFilter>> filtersMap, Function<PackageInfo, C[]> componentArrayInPackage, BiConsumer<PackageInfo, C[]> componentsSetter, C newComponent, boolean updateIfExists)498 private <C extends ComponentInfo> C addComponent( 499 SortedMap<ComponentName, List<IntentFilter>> filtersMap, 500 Function<PackageInfo, C[]> componentArrayInPackage, 501 BiConsumer<PackageInfo, C[]> componentsSetter, 502 C newComponent, 503 boolean updateIfExists) { 504 synchronized (lock) { 505 String packageName = newComponent.packageName; 506 if (packageName == null && newComponent.applicationInfo != null) { 507 packageName = newComponent.applicationInfo.packageName; 508 } 509 if (packageName == null) { 510 throw new IllegalArgumentException("Component needs a package name"); 511 } 512 if (newComponent.name == null) { 513 throw new IllegalArgumentException("Component needs a name"); 514 } 515 PackageInfo packageInfo = packageInfos.get(packageName); 516 if (packageInfo == null) { 517 packageInfo = new PackageInfo(); 518 packageInfo.packageName = packageName; 519 packageInfo.applicationInfo = newComponent.applicationInfo; 520 installPackage(packageInfo); 521 packageInfo = packageInfos.get(packageName); 522 } 523 newComponent.applicationInfo = packageInfo.applicationInfo; 524 C[] components = componentArrayInPackage.apply(packageInfo); 525 if (components == null) { 526 @SuppressWarnings("unchecked") 527 C[] newComponentArray = (C[]) Array.newInstance(newComponent.getClass(), 0); 528 components = newComponentArray; 529 } else { 530 for (int i = 0; i < components.length; i++) { 531 if (newComponent.name.equals(components[i].name)) { 532 if (updateIfExists) { 533 components[i] = newComponent; 534 } 535 return components[i]; 536 } 537 } 538 } 539 components = Arrays.copyOf(components, components.length + 1); 540 componentsSetter.accept(packageInfo, components); 541 components[components.length - 1] = newComponent; 542 543 filtersMap.put( 544 new ComponentName(newComponent.packageName, newComponent.name), new ArrayList<>()); 545 return newComponent; 546 } 547 } 548 549 @Nullable removeComponent( ComponentName componentName, SortedMap<ComponentName, List<IntentFilter>> filtersMap, Function<PackageInfo, C[]> componentArrayInPackage, BiConsumer<PackageInfo, C[]> componentsSetter)550 private <C extends ComponentInfo> C removeComponent( 551 ComponentName componentName, 552 SortedMap<ComponentName, List<IntentFilter>> filtersMap, 553 Function<PackageInfo, C[]> componentArrayInPackage, 554 BiConsumer<PackageInfo, C[]> componentsSetter) { 555 synchronized (lock) { 556 filtersMap.remove(componentName); 557 String packageName = componentName.getPackageName(); 558 PackageInfo packageInfo = packageInfos.get(packageName); 559 if (packageInfo == null) { 560 return null; 561 } 562 C[] components = componentArrayInPackage.apply(packageInfo); 563 if (components == null) { 564 return null; 565 } 566 for (int i = 0; i < components.length; i++) { 567 C component = components[i]; 568 if (componentName.getClassName().equals(component.name)) { 569 C[] newComponents; 570 if (components.length == 1) { 571 newComponents = null; 572 } else { 573 newComponents = Arrays.copyOf(components, components.length - 1); 574 System.arraycopy(components, i + 1, newComponents, i, components.length - i - 1); 575 } 576 componentsSetter.accept(packageInfo, newComponents); 577 return component; 578 } 579 } 580 return null; 581 } 582 } 583 584 /** 585 * Settings for a particular package. 586 * 587 * <p>This class mirrors {@link com.android.server.pm.PackageSetting}, which is used by {@link 588 * PackageManager}. 589 */ 590 public static class PackageSetting { 591 592 /** Whether the package is suspended in {@link PackageManager}. */ 593 private boolean suspended = false; 594 595 /** The message to be displayed to the user when they try to launch the app. */ 596 private String dialogMessage = null; 597 598 /** 599 * The info for how to display the dialog that shows to the user when they try to launch the 600 * app. On Q, one of this field or dialogMessage will be present when a package is suspended. 601 */ 602 private Object dialogInfo = null; 603 604 /** An optional {@link PersistableBundle} shared with the app. */ 605 private PersistableBundle suspendedAppExtras = null; 606 607 /** An optional {@link PersistableBundle} shared with the launcher. */ 608 private PersistableBundle suspendedLauncherExtras = null; 609 PackageSetting()610 public PackageSetting() {} 611 PackageSetting(PackageSetting that)612 public PackageSetting(PackageSetting that) { 613 this.suspended = that.suspended; 614 this.dialogMessage = that.dialogMessage; 615 this.dialogInfo = that.dialogInfo; 616 this.suspendedAppExtras = deepCopyNullablePersistableBundle(that.suspendedAppExtras); 617 this.suspendedLauncherExtras = 618 deepCopyNullablePersistableBundle(that.suspendedLauncherExtras); 619 } 620 621 /** 622 * Sets the suspension state of the package. 623 * 624 * <p>If {@code suspended} is false, {@code dialogInfo}, {@code appExtras}, and {@code 625 * launcherExtras} will be ignored. 626 */ setSuspended( boolean suspended, String dialogMessage, Object dialogInfo, PersistableBundle appExtras, PersistableBundle launcherExtras)627 void setSuspended( 628 boolean suspended, 629 String dialogMessage, 630 /* SuspendDialogInfo */ Object dialogInfo, 631 PersistableBundle appExtras, 632 PersistableBundle launcherExtras) { 633 Preconditions.checkArgument(dialogMessage == null || dialogInfo == null); 634 this.suspended = suspended; 635 this.dialogMessage = suspended ? dialogMessage : null; 636 this.dialogInfo = suspended ? dialogInfo : null; 637 this.suspendedAppExtras = suspended ? deepCopyNullablePersistableBundle(appExtras) : null; 638 this.suspendedLauncherExtras = 639 suspended ? deepCopyNullablePersistableBundle(launcherExtras) : null; 640 } 641 isSuspended()642 public boolean isSuspended() { 643 return suspended; 644 } 645 getDialogMessage()646 public String getDialogMessage() { 647 return dialogMessage; 648 } 649 getDialogInfo()650 public Object getDialogInfo() { 651 return dialogInfo; 652 } 653 getSuspendedAppExtras()654 public PersistableBundle getSuspendedAppExtras() { 655 return suspendedAppExtras; 656 } 657 getSuspendedLauncherExtras()658 public PersistableBundle getSuspendedLauncherExtras() { 659 return suspendedLauncherExtras; 660 } 661 deepCopyNullablePersistableBundle(PersistableBundle bundle)662 private static PersistableBundle deepCopyNullablePersistableBundle(PersistableBundle bundle) { 663 return bundle == null ? null : bundle.deepCopy(); 664 } 665 } 666 667 static final Map<String, PackageSetting> packageSettings = new HashMap<>(); 668 669 // From com.android.server.pm.PackageManagerService.compareSignatures(). compareSignature(Signature[] signatures1, Signature[] signatures2)670 static int compareSignature(Signature[] signatures1, Signature[] signatures2) { 671 if (signatures1 == null) { 672 return (signatures2 == null) ? SIGNATURE_NEITHER_SIGNED : SIGNATURE_FIRST_NOT_SIGNED; 673 } 674 if (signatures2 == null) { 675 return SIGNATURE_SECOND_NOT_SIGNED; 676 } 677 if (signatures1.length != signatures2.length) { 678 return SIGNATURE_NO_MATCH; 679 } 680 HashSet<Signature> signatures1set = new HashSet<>(asList(signatures1)); 681 HashSet<Signature> signatures2set = new HashSet<>(asList(signatures2)); 682 return signatures1set.equals(signatures2set) ? SIGNATURE_MATCH : SIGNATURE_NO_MATCH; 683 } 684 685 // TODO(christianw): reconcile with AndroidTestEnvironment.setUpPackageStorage setUpPackageStorage(ApplicationInfo applicationInfo)686 private static void setUpPackageStorage(ApplicationInfo applicationInfo) { 687 if (applicationInfo.sourceDir == null) { 688 applicationInfo.sourceDir = createTempDir(applicationInfo.packageName + "-sourceDir"); 689 } 690 691 if (applicationInfo.dataDir == null) { 692 applicationInfo.dataDir = createTempDir(applicationInfo.packageName + "-dataDir"); 693 } 694 if (applicationInfo.publicSourceDir == null) { 695 applicationInfo.publicSourceDir = applicationInfo.sourceDir; 696 } 697 if (RuntimeEnvironment.getApiLevel() >= N) { 698 applicationInfo.credentialProtectedDataDir = createTempDir("userDataDir"); 699 applicationInfo.deviceProtectedDataDir = createTempDir("deviceDataDir"); 700 } 701 } 702 createTempDir(String name)703 private static String createTempDir(String name) { 704 return RuntimeEnvironment.getTempDirectory() 705 .createIfNotExists(name) 706 .toAbsolutePath() 707 .toString(); 708 } 709 710 /** 711 * Sets extra resolve infos for an intent. 712 * 713 * <p>Those entries are added to whatever might be in the manifest already. 714 * 715 * <p>Note that all resolve infos will have {@link ResolveInfo#isDefault} field set to {@code 716 * true} to allow their resolution for implicit intents. If this is not what you want, then you 717 * still have the reference to those ResolveInfos, and you can set the field back to {@code 718 * false}. 719 * 720 * @deprecated see the note on {@link #addResolveInfoForIntent(Intent, ResolveInfo)}. 721 */ 722 @Deprecated setResolveInfosForIntent(Intent intent, List<ResolveInfo> info)723 public void setResolveInfosForIntent(Intent intent, List<ResolveInfo> info) { 724 resolveInfoForIntent.remove(intent); 725 for (ResolveInfo resolveInfo : info) { 726 addResolveInfoForIntent(intent, resolveInfo); 727 } 728 } 729 730 /** 731 * @deprecated see note on {@link #addResolveInfoForIntent(Intent, ResolveInfo)}. 732 */ 733 @Deprecated addResolveInfoForIntent(Intent intent, List<ResolveInfo> info)734 public void addResolveInfoForIntent(Intent intent, List<ResolveInfo> info) { 735 setResolveInfosForIntent(intent, info); 736 } 737 738 /** 739 * Adds extra resolve info for an intent. 740 * 741 * <p>Note that this resolve info will have {@link ResolveInfo#isDefault} field set to {@code 742 * true} to allow its resolution for implicit intents. If this is not what you want, then please 743 * use {@link #addResolveInfoForIntentNoDefaults} instead. 744 * 745 * @deprecated use {@link #addIntentFilterForComponent} instead and if the component doesn't exist 746 * add it using any of {@link #installPackage}, {@link #addOrUpdateActivity}, {@link 747 * #addActivityIfNotPresent} or their counterparts for other types of components. 748 */ 749 @Deprecated addResolveInfoForIntent(Intent intent, ResolveInfo info)750 public void addResolveInfoForIntent(Intent intent, ResolveInfo info) { 751 info.isDefault = true; 752 ComponentInfo[] componentInfos = 753 new ComponentInfo[] {info.activityInfo, info.serviceInfo, info.providerInfo}; 754 for (ComponentInfo component : componentInfos) { 755 if (component != null && component.applicationInfo != null) { 756 component.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED; 757 if (component.applicationInfo.processName == null) { 758 component.applicationInfo.processName = component.applicationInfo.packageName; 759 } 760 } 761 } 762 if (info.match == 0) { 763 info.match = Integer.MAX_VALUE; // make sure, that this is as good match as possible. 764 } 765 addResolveInfoForIntentNoDefaults(intent, info); 766 } 767 768 /** 769 * Adds the {@code info} as {@link ResolveInfo} for the intent but without applying any default 770 * values. 771 * 772 * <p>In particular it will not make the {@link ResolveInfo#isDefault} field {@code true}, that 773 * means that this resolve info will not resolve for {@link Intent#resolveActivity} and {@link 774 * Context#startActivity}. 775 * 776 * @deprecated see the note on {@link #addResolveInfoForIntent(Intent, ResolveInfo)}. 777 */ 778 @Deprecated addResolveInfoForIntentNoDefaults(Intent intent, ResolveInfo info)779 public void addResolveInfoForIntentNoDefaults(Intent intent, ResolveInfo info) { 780 Preconditions.checkNotNull(info); 781 List<ResolveInfo> infoList = resolveInfoForIntent.get(intent); 782 if (infoList == null) { 783 infoList = new ArrayList<>(); 784 resolveInfoForIntent.put(intent, infoList); 785 } 786 infoList.add(info); 787 } 788 789 /** 790 * Removes {@link ResolveInfo}s registered using {@link #addResolveInfoForIntent}. 791 * 792 * @deprecated see note on {@link #addResolveInfoForIntent(Intent, ResolveInfo)}. 793 */ 794 @Deprecated removeResolveInfosForIntent(Intent intent, String packageName)795 public void removeResolveInfosForIntent(Intent intent, String packageName) { 796 List<ResolveInfo> infoList = resolveInfoForIntent.get(intent); 797 if (infoList == null) { 798 infoList = new ArrayList<>(); 799 resolveInfoForIntent.put(intent, infoList); 800 } 801 802 for (Iterator<ResolveInfo> iterator = infoList.iterator(); iterator.hasNext(); ) { 803 ResolveInfo resolveInfo = iterator.next(); 804 if (getPackageName(resolveInfo).equals(packageName)) { 805 iterator.remove(); 806 } 807 } 808 } 809 getPackageName(ResolveInfo resolveInfo)810 private static String getPackageName(ResolveInfo resolveInfo) { 811 if (resolveInfo.resolvePackageName != null) { 812 return resolveInfo.resolvePackageName; 813 } else if (resolveInfo.activityInfo != null) { 814 return resolveInfo.activityInfo.packageName; 815 } else if (resolveInfo.serviceInfo != null) { 816 return resolveInfo.serviceInfo.packageName; 817 } else if (resolveInfo.providerInfo != null) { 818 return resolveInfo.providerInfo.packageName; 819 } 820 throw new IllegalStateException( 821 "Could not find package name for ResolveInfo " + resolveInfo.toString()); 822 } 823 addActivityIcon(ComponentName component, Drawable drawable)824 public void addActivityIcon(ComponentName component, Drawable drawable) { 825 drawableList.put(component, drawable); 826 } 827 addActivityIcon(Intent intent, Drawable drawable)828 public void addActivityIcon(Intent intent, Drawable drawable) { 829 drawableList.put(intent.getComponent(), drawable); 830 } 831 setApplicationIcon(String packageName, Drawable drawable)832 public void setApplicationIcon(String packageName, Drawable drawable) { 833 applicationIcons.put(packageName, drawable); 834 } 835 setUnbadgedApplicationIcon(String packageName, Drawable drawable)836 public void setUnbadgedApplicationIcon(String packageName, Drawable drawable) { 837 unbadgedApplicationIcons.put(packageName, drawable); 838 } 839 840 /** 841 * Return the flags set in call to {@link 842 * android.app.ApplicationPackageManager#setComponentEnabledSetting(ComponentName, int, int)}. 843 * 844 * @param componentName The component name. 845 * @return The flags. 846 */ getComponentEnabledSettingFlags(ComponentName componentName)847 public int getComponentEnabledSettingFlags(ComponentName componentName) { 848 ComponentState state = componentList.get(componentName); 849 return state != null ? state.flags : 0; 850 } 851 852 /** 853 * Installs a module with the {@link PackageManager} as long as it is not {@code null} 854 * 855 * <p>In order to create ModuleInfo objects in a valid state please use {@link ModuleInfoBuilder}. 856 */ installModule(Object moduleInfoObject)857 public void installModule(Object moduleInfoObject) { 858 synchronized (lock) { 859 ModuleInfo moduleInfo = (ModuleInfo) moduleInfoObject; 860 if (moduleInfo != null) { 861 moduleInfos.put(moduleInfo.getPackageName(), moduleInfo); 862 // Checking to see if package exists in the system 863 if (packageInfos.get(moduleInfo.getPackageName()) == null) { 864 ApplicationInfo applicationInfo = new ApplicationInfo(); 865 applicationInfo.packageName = moduleInfo.getPackageName(); 866 applicationInfo.name = moduleInfo.getName().toString(); 867 868 PackageInfo packageInfo = new PackageInfo(); 869 packageInfo.applicationInfo = applicationInfo; 870 packageInfo.packageName = moduleInfo.getPackageName(); 871 installPackage(packageInfo); 872 } 873 } 874 } 875 } 876 877 /** 878 * Deletes a module when given the module's package name {@link ModuleInfo} be sure to give the 879 * correct name as this method does not ensure existence of the module before deletion. Since 880 * module installation ensures that a package exists in the device, also delete the package for 881 * full deletion. 882 * 883 * @param packageName should be the value of {@link ModuleInfo#getPackageName}. 884 * @return deleted module of {@code null} if no module with this name exists. 885 */ deleteModule(String packageName)886 public Object deleteModule(String packageName) { 887 synchronized (lock) { 888 // Removes the accompanying package installed with the module 889 return moduleInfos.remove(packageName); 890 } 891 } 892 893 /** 894 * Installs a package with the {@link PackageManager}. 895 * 896 * <p>In order to create PackageInfo objects in a valid state please use {@link 897 * androidx.test.core.content.pm.PackageInfoBuilder}. 898 * 899 * <p>This method automatically simulates instalation of a package in the system, so it adds a 900 * flag {@link ApplicationInfo#FLAG_INSTALLED} to the application info and makes sure it exits. It 901 * will update applicationInfo in package components as well. 902 * 903 * <p>If you don't want the package to be installed, use {@link #addPackageNoDefaults} instead. 904 */ installPackage(PackageInfo packageInfo)905 public void installPackage(PackageInfo packageInfo) { 906 ApplicationInfo appInfo = packageInfo.applicationInfo; 907 if (appInfo == null) { 908 appInfo = new ApplicationInfo(); 909 packageInfo.applicationInfo = appInfo; 910 } 911 if (appInfo.packageName == null) { 912 appInfo.packageName = packageInfo.packageName; 913 } 914 if (appInfo.processName == null) { 915 appInfo.processName = appInfo.packageName; 916 } 917 if (appInfo.targetSdkVersion == 0) { 918 appInfo.targetSdkVersion = RuntimeEnvironment.getApiLevel(); 919 } 920 appInfo.flags |= ApplicationInfo.FLAG_INSTALLED; 921 ComponentInfo[][] componentInfoArrays = 922 new ComponentInfo[][] { 923 packageInfo.activities, 924 packageInfo.services, 925 packageInfo.providers, 926 packageInfo.receivers, 927 }; 928 int uniqueNameCounter = 0; 929 for (ComponentInfo[] componentInfos : componentInfoArrays) { 930 if (componentInfos == null) { 931 continue; 932 } 933 for (ComponentInfo componentInfo : componentInfos) { 934 if (componentInfo.name == null) { 935 componentInfo.name = appInfo.packageName + ".DefaultName" + uniqueNameCounter++; 936 componentInfo.packageName = packageInfo.packageName; 937 } 938 componentInfo.applicationInfo = appInfo; 939 componentInfo.packageName = appInfo.packageName; 940 if (componentInfo.processName == null) { 941 componentInfo.processName = appInfo.processName; 942 } 943 } 944 } 945 addPackageNoDefaults(packageInfo); 946 } 947 948 /** Adds install source information for a package. */ setInstallSourceInfo( String packageName, String initiatingPackage, String installerPackage)949 public void setInstallSourceInfo( 950 String packageName, String initiatingPackage, String installerPackage) { 951 packageInstallSourceInfoMap.put( 952 packageName, new InstallSourceInfo(initiatingPackage, null, null, installerPackage)); 953 } 954 955 /** Adds install source information for a package. */ setInstallSourceInfo( String packageName, @Nullable String initiatingPackageName, @Nullable SigningInfo initiatingPackageSigningInfo, @Nullable String originatingPackageName, @Nullable String installingPackageName, @Nullable String updateOwnerPackageName, int packageSource)956 public void setInstallSourceInfo( 957 String packageName, 958 @Nullable String initiatingPackageName, 959 @Nullable SigningInfo initiatingPackageSigningInfo, 960 @Nullable String originatingPackageName, 961 @Nullable String installingPackageName, 962 @Nullable String updateOwnerPackageName, 963 int packageSource) { 964 packageInstallSourceInfoMap.put( 965 packageName, 966 new InstallSourceInfo( 967 initiatingPackageName, 968 initiatingPackageSigningInfo, 969 originatingPackageName, 970 installingPackageName, 971 updateOwnerPackageName, 972 packageSource)); 973 } 974 975 /** 976 * Adds a package to the {@link PackageManager}, but doesn't set any default values on it. 977 * 978 * <p>Right now it will not set {@link ApplicationInfo#FLAG_INSTALLED} flag on its application, so 979 * if not set explicitly, it will be treated as not installed. 980 */ addPackageNoDefaults(PackageInfo packageInfo)981 public void addPackageNoDefaults(PackageInfo packageInfo) { 982 PackageStats packageStats = new PackageStats(packageInfo.packageName); 983 addPackage(packageInfo, packageStats); 984 } 985 986 /** 987 * Installs a package with its stats with the {@link PackageManager}. 988 * 989 * <p>This method doesn't add any defaults to the {@code packageInfo} parameters. You should make 990 * sure it is valid (see {@link #installPackage(PackageInfo)}). 991 */ addPackage(PackageInfo packageInfo, PackageStats packageStats)992 public void addPackage(PackageInfo packageInfo, PackageStats packageStats) { 993 synchronized (lock) { 994 if (packageInfo.applicationInfo != null 995 && (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) == 0) { 996 Log.w(TAG, "Adding not installed package: " + packageInfo.packageName); 997 } 998 Preconditions.checkArgument(packageInfo.packageName.equals(packageStats.packageName)); 999 1000 if (packageInfo.permissions != null) { 1001 for (PermissionInfo permissionInfo : packageInfo.permissions) { 1002 if (AOSP_PLATFORM_PERMISSIONS.containsKey(permissionInfo.name) 1003 || permissionInfo.name.startsWith(AOSP_PLATFORM_PERMISSION_PREFIX)) { 1004 throw new IllegalArgumentException( 1005 "Permission " 1006 + permissionInfo.name 1007 + " is a platform permission. Do not declare it as part of the package or test" 1008 + " app manifest."); 1009 } 1010 } 1011 } 1012 1013 packageInfos.put(packageInfo.packageName, packageInfo); 1014 packageStatsMap.put(packageInfo.packageName, packageStats); 1015 1016 packageSettings.put(packageInfo.packageName, new PackageSetting()); 1017 1018 applicationEnabledSettingMap.put( 1019 packageInfo.packageName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT); 1020 if (packageInfo.applicationInfo != null) { 1021 uidForPackage.put(packageInfo.packageName, packageInfo.applicationInfo.uid); 1022 namesForUid.put(packageInfo.applicationInfo.uid, packageInfo.packageName); 1023 } 1024 } 1025 } 1026 1027 /** 1028 * @deprecated Use {@link #installPackage(PackageInfo)} instead. 1029 */ 1030 @Deprecated addPackage(String packageName)1031 public void addPackage(String packageName) { 1032 PackageInfo packageInfo = new PackageInfo(); 1033 packageInfo.packageName = packageName; 1034 1035 ApplicationInfo applicationInfo = new ApplicationInfo(); 1036 1037 applicationInfo.packageName = packageName; 1038 // TODO: setUpPackageStorage should be in installPackage but we need to fix all tests first 1039 setUpPackageStorage(applicationInfo); 1040 packageInfo.applicationInfo = applicationInfo; 1041 installPackage(packageInfo); 1042 } 1043 1044 /** 1045 * @deprecated Use {@link #installPackage} instead. 1046 */ 1047 @Deprecated 1048 @InlineMe(replacement = "this.installPackage(packageInfo)") addPackage(PackageInfo packageInfo)1049 public final void addPackage(PackageInfo packageInfo) { 1050 installPackage(packageInfo); 1051 } 1052 1053 /** 1054 * Testing API allowing to retrieve internal package representation. 1055 * 1056 * <p>This will allow to modify the package in a way visible to Robolectric, as this is 1057 * Robolectric's internal full package representation. 1058 * 1059 * <p>Note that maybe a better way is to just modify the test manifest to make those modifications 1060 * in a standard way. 1061 * 1062 * <p>Retrieving package info using {@link PackageManager#getPackageInfo} / {@link 1063 * PackageManager#getApplicationInfo} will return defensive copies that will be stripped out of 1064 * information according to provided flags. Don't use it to modify Robolectric state. 1065 */ getInternalMutablePackageInfo(String packageName)1066 public PackageInfo getInternalMutablePackageInfo(String packageName) { 1067 synchronized (lock) { 1068 return packageInfos.get(packageName); 1069 } 1070 } 1071 addPermissionInfo(PermissionInfo permissionInfo)1072 public void addPermissionInfo(PermissionInfo permissionInfo) { 1073 extraPermissions.put(permissionInfo.name, permissionInfo); 1074 } 1075 1076 /** 1077 * Adds {@code packageName} to the list of changed packages for the particular {@code 1078 * sequenceNumber}. 1079 * 1080 * @param sequenceNumber has to be >= 0 1081 * @param packageName name of the package that was changed 1082 */ addChangedPackage(int sequenceNumber, String packageName)1083 public void addChangedPackage(int sequenceNumber, String packageName) { 1084 if (sequenceNumber < 0) { 1085 return; 1086 } 1087 sequenceNumberChangedPackagesMap.put(sequenceNumber, packageName); 1088 } 1089 1090 /** 1091 * Allows overriding or adding permission-group elements. These would be otherwise specified by 1092 * either (the 1093 * system)[https://developer.android.com/guide/topics/permissions/requesting.html#perm-groups] or 1094 * by (the app 1095 * itself)[https://developer.android.com/guide/topics/manifest/permission-group-element.html], as 1096 * part of its manifest 1097 * 1098 * <p>{@link android.content.pm.PackageParser.PermissionGroup}s added through this method have 1099 * precedence over those specified with the same name by one of the aforementioned methods. 1100 * 1101 * @see PackageManager#getAllPermissionGroups(int) 1102 * @see PackageManager#getPermissionGroupInfo(String, int) 1103 */ addPermissionGroupInfo(PermissionGroupInfo permissionGroupInfo)1104 public void addPermissionGroupInfo(PermissionGroupInfo permissionGroupInfo) { 1105 permissionGroups.put(permissionGroupInfo.name, permissionGroupInfo); 1106 } 1107 removePackage(String packageName)1108 public void removePackage(String packageName) { 1109 synchronized (lock) { 1110 packageInfos.remove(packageName); 1111 1112 packageSettings.remove(packageName); 1113 } 1114 } 1115 setSystemFeature(String name, boolean supported)1116 public void setSystemFeature(String name, boolean supported) { 1117 systemFeatureList.put(name, supported); 1118 } 1119 addDrawableResolution(String packageName, int resourceId, Drawable drawable)1120 public void addDrawableResolution(String packageName, int resourceId, Drawable drawable) { 1121 drawables.put(new Pair(packageName, resourceId), drawable); 1122 } 1123 setNameForUid(int uid, String name)1124 public void setNameForUid(int uid, String name) { 1125 namesForUid.put(uid, name); 1126 } 1127 setPackagesForCallingUid(String... packagesForCallingUid)1128 public void setPackagesForCallingUid(String... packagesForCallingUid) { 1129 packagesForUid.put(Binder.getCallingUid(), packagesForCallingUid); 1130 for (String packageName : packagesForCallingUid) { 1131 uidForPackage.put(packageName, Binder.getCallingUid()); 1132 } 1133 } 1134 setPackagesForUid(int uid, String... packagesForCallingUid)1135 public void setPackagesForUid(int uid, String... packagesForCallingUid) { 1136 packagesForUid.put(uid, packagesForCallingUid); 1137 for (String packageName : packagesForCallingUid) { 1138 uidForPackage.put(packageName, uid); 1139 } 1140 } 1141 1142 @Implementation 1143 @Nullable getPackagesForUid(int uid)1144 protected String[] getPackagesForUid(int uid) { 1145 return packagesForUid.get(uid); 1146 } 1147 setPackageArchiveInfo(String archiveFilePath, PackageInfo packageInfo)1148 public void setPackageArchiveInfo(String archiveFilePath, PackageInfo packageInfo) { 1149 packageArchiveInfo.put(archiveFilePath, packageInfo); 1150 } 1151 getVerificationResult(int id)1152 public int getVerificationResult(int id) { 1153 Integer result = verificationResults.get(id); 1154 if (result == null) { 1155 // 0 isn't a "valid" result, so we can check for the case when verification isn't 1156 // called, if needed 1157 return 0; 1158 } 1159 return result; 1160 } 1161 getVerificationExtendedTimeout(int id)1162 public long getVerificationExtendedTimeout(int id) { 1163 synchronized (lock) { 1164 return verificationTimeoutExtension.getOrDefault(id, 0L); 1165 } 1166 } 1167 getVerificationCodeAtTimeoutExtension(int id)1168 public int getVerificationCodeAtTimeoutExtension(int id) { 1169 synchronized (lock) { 1170 return verificationCodeAtTimeoutExtension.getOrDefault(id, VERIFICATION_ALLOW); 1171 } 1172 } 1173 triggerInstallVerificationTimeout(Application appContext, int id)1174 public void triggerInstallVerificationTimeout(Application appContext, int id) { 1175 Intent intent = new Intent(Intent.ACTION_PACKAGE_VERIFIED); 1176 intent.putExtra(EXTRA_VERIFICATION_ID, id); 1177 intent.putExtra( 1178 PackageManager.EXTRA_VERIFICATION_RESULT, getVerificationCodeAtTimeoutExtension(id)); 1179 1180 // Send PACKAGE_VERIFIED broadcast to trigger the verification timeout. 1181 // Replacement api does not return the actual receiver objects. 1182 @SuppressWarnings("deprecation") 1183 List<BroadcastReceiver> receivers = 1184 ShadowApplication.getShadowInstrumentation().getReceiversForIntent(intent); 1185 for (BroadcastReceiver receiver : receivers) { 1186 receiver.onReceive(appContext, intent); 1187 } 1188 } 1189 setShouldShowRequestPermissionRationale(String permission, boolean show)1190 public void setShouldShowRequestPermissionRationale(String permission, boolean show) { 1191 permissionRationaleMap.put(permission, show); 1192 } 1193 addSystemAvailableFeature(FeatureInfo featureInfo)1194 public void addSystemAvailableFeature(FeatureInfo featureInfo) { 1195 systemAvailableFeatures.add(featureInfo); 1196 } 1197 clearSystemAvailableFeatures()1198 public void clearSystemAvailableFeatures() { 1199 systemAvailableFeatures.clear(); 1200 } 1201 1202 /** Adds a value to be returned by {@link PackageManager#getSystemSharedLibraryNames()}. */ addSystemSharedLibraryName(String name)1203 public void addSystemSharedLibraryName(String name) { 1204 systemSharedLibraryNames.add(name); 1205 } 1206 1207 /** Clears the values returned by {@link PackageManager#getSystemSharedLibraryNames()}. */ clearSystemSharedLibraryNames()1208 public void clearSystemSharedLibraryNames() { 1209 systemSharedLibraryNames.clear(); 1210 } 1211 1212 /** 1213 * Adds a canonical package name for a package. 1214 * 1215 * <p>This will be reflected when calling {@link 1216 * PackageManager#currentToCanonicalPackageNames(String[])} or {@link 1217 * PackageManager#canonicalToCurrentPackageNames(String[])} (String[])}. 1218 */ addCanonicalName(String currentName, String canonicalName)1219 public void addCanonicalName(String currentName, String canonicalName) { 1220 currentToCanonicalNames.put(currentName, canonicalName); 1221 canonicalToCurrentNames.put(canonicalName, currentName); 1222 } 1223 1224 /** 1225 * Sets if the {@link PackageManager} is allowed to request package installs through package 1226 * installer. 1227 */ setCanRequestPackageInstalls(boolean canRequestPackageInstalls)1228 public void setCanRequestPackageInstalls(boolean canRequestPackageInstalls) { 1229 ShadowPackageManager.canRequestPackageInstalls = canRequestPackageInstalls; 1230 } 1231 1232 @Implementation(minSdk = N) queryBroadcastReceiversAsUser( Intent intent, int flags, UserHandle userHandle)1233 protected List<ResolveInfo> queryBroadcastReceiversAsUser( 1234 Intent intent, int flags, UserHandle userHandle) { 1235 return null; 1236 } 1237 1238 @Implementation queryBroadcastReceivers( Intent intent, int flags, @UserIdInt int userId)1239 protected List<ResolveInfo> queryBroadcastReceivers( 1240 Intent intent, int flags, @UserIdInt int userId) { 1241 return null; 1242 } 1243 1244 @Implementation getPackageArchiveInfo(String archiveFilePath, int flags)1245 protected PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) { 1246 PackageInfo shadowPackageInfo = getShadowPackageArchiveInfo(archiveFilePath, flags); 1247 if (shadowPackageInfo != null) { 1248 return shadowPackageInfo; 1249 } else { 1250 return reflector(PackageManagerReflector.class, realPackageManager) 1251 .getPackageArchiveInfo(archiveFilePath, flags); 1252 } 1253 } 1254 getShadowPackageArchiveInfo(String archiveFilePath, int flags)1255 protected PackageInfo getShadowPackageArchiveInfo(String archiveFilePath, int flags) { 1256 synchronized (lock) { 1257 if (packageArchiveInfo.containsKey(archiveFilePath)) { 1258 return packageArchiveInfo.get(archiveFilePath); 1259 } 1260 1261 List<PackageInfo> result = new ArrayList<>(); 1262 for (PackageInfo packageInfo : packageInfos.values()) { 1263 if (applicationEnabledSettingMap.get(packageInfo.packageName) 1264 != COMPONENT_ENABLED_STATE_DISABLED 1265 || (flags & MATCH_UNINSTALLED_PACKAGES) == MATCH_UNINSTALLED_PACKAGES) { 1266 result.add(packageInfo); 1267 } 1268 } 1269 1270 List<PackageInfo> packages = result; 1271 for (PackageInfo aPackage : packages) { 1272 ApplicationInfo appInfo = aPackage.applicationInfo; 1273 if (appInfo != null && archiveFilePath.equals(appInfo.sourceDir)) { 1274 return aPackage; 1275 } 1276 } 1277 return null; 1278 } 1279 } 1280 1281 @Implementation freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer)1282 protected void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer) {} 1283 1284 @Implementation freeStorage(long freeStorageSize, IntentSender pi)1285 protected void freeStorage(long freeStorageSize, IntentSender pi) {} 1286 1287 /** 1288 * Uninstalls the package from the system in a way, that will allow its discovery through {@link 1289 * PackageManager#MATCH_UNINSTALLED_PACKAGES}. 1290 */ deletePackage(String packageName)1291 public void deletePackage(String packageName) { 1292 synchronized (lock) { 1293 deletedPackages.add(packageName); 1294 packageInfos.remove(packageName); 1295 mapForPackage(activityFilters, packageName).clear(); 1296 mapForPackage(serviceFilters, packageName).clear(); 1297 mapForPackage(providerFilters, packageName).clear(); 1298 mapForPackage(receiverFilters, packageName).clear(); 1299 moduleInfos.remove(packageName); 1300 } 1301 } 1302 1303 @Implementation deletePackage(String packageName, IPackageDeleteObserver observer, int flags)1304 protected void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) { 1305 pendingDeleteCallbacks.put(packageName, observer); 1306 } 1307 1308 /** 1309 * Runs the callbacks pending from calls to {@link PackageManager#deletePackage(String, 1310 * IPackageDeleteObserver, int)} 1311 */ doPendingUninstallCallbacks()1312 public void doPendingUninstallCallbacks() { 1313 synchronized (lock) { 1314 boolean hasDeletePackagesPermission = false; 1315 String[] requestedPermissions = 1316 packageInfos.get(RuntimeEnvironment.getApplication().getPackageName()) 1317 .requestedPermissions; 1318 if (requestedPermissions != null) { 1319 for (String permission : requestedPermissions) { 1320 if (Manifest.permission.DELETE_PACKAGES.equals(permission)) { 1321 hasDeletePackagesPermission = true; 1322 break; 1323 } 1324 } 1325 } 1326 1327 for (String packageName : pendingDeleteCallbacks.keySet()) { 1328 int resultCode = PackageManager.DELETE_FAILED_INTERNAL_ERROR; 1329 1330 PackageInfo removed = packageInfos.get(packageName); 1331 if (hasDeletePackagesPermission && removed != null) { 1332 deletePackage(packageName); 1333 resultCode = PackageManager.DELETE_SUCCEEDED; 1334 } 1335 1336 try { 1337 pendingDeleteCallbacks.get(packageName).packageDeleted(packageName, resultCode); 1338 } catch (RemoteException e) { 1339 throw new RuntimeException(e); 1340 } 1341 } 1342 pendingDeleteCallbacks.clear(); 1343 } 1344 } 1345 1346 /** 1347 * Returns package names successfully deleted with {@link PackageManager#deletePackage(String, 1348 * IPackageDeleteObserver, int)} Note that like real {@link PackageManager} the calling context 1349 * must have {@link android.Manifest.permission#DELETE_PACKAGES} permission set. 1350 */ getDeletedPackages()1351 public Set<String> getDeletedPackages() { 1352 synchronized (lock) { 1353 return deletedPackages; 1354 } 1355 } 1356 queryOverriddenIntents(Intent intent, int flags)1357 protected List<ResolveInfo> queryOverriddenIntents(Intent intent, int flags) { 1358 List<ResolveInfo> overrides = resolveInfoForIntent.get(intent); 1359 if (overrides == null) { 1360 return ImmutableList.of(); 1361 } 1362 return overrides.stream().map(ShadowResolveInfo::newResolveInfo).collect(toImmutableList()); 1363 } 1364 1365 /** 1366 * Internal use only. 1367 * 1368 * @param appPackage 1369 */ addPackageInternal(Package appPackage)1370 public void addPackageInternal(Package appPackage) { 1371 int flags = 1372 GET_ACTIVITIES 1373 | GET_RECEIVERS 1374 | GET_SERVICES 1375 | GET_PROVIDERS 1376 | GET_INSTRUMENTATION 1377 | GET_INTENT_FILTERS 1378 | GET_SIGNATURES 1379 | GET_RESOLVED_FILTER 1380 | GET_META_DATA 1381 | GET_GIDS 1382 | MATCH_DISABLED_COMPONENTS 1383 | GET_SHARED_LIBRARY_FILES 1384 | GET_URI_PERMISSION_PATTERNS 1385 | GET_PERMISSIONS 1386 | MATCH_UNINSTALLED_PACKAGES 1387 | GET_CONFIGURATIONS 1388 | MATCH_DISABLED_UNTIL_USED_COMPONENTS 1389 | MATCH_DIRECT_BOOT_UNAWARE 1390 | MATCH_DIRECT_BOOT_AWARE; 1391 1392 for (PermissionGroup permissionGroup : appPackage.permissionGroups) { 1393 PermissionGroupInfo permissionGroupInfo = 1394 PackageParser.generatePermissionGroupInfo(permissionGroup, flags); 1395 1396 if (AOSP_PLATFORM_PERMISSION_GROUPS.containsKey(permissionGroupInfo.name) 1397 || permissionGroupInfo.name.startsWith(AOSP_PLATFORM_PERMISSION_GROUP_PREFIX)) { 1398 throw new IllegalArgumentException( 1399 "Permission group " 1400 + permissionGroupInfo.name 1401 + " is a platform permission group. Do not declare it as part of the test app" 1402 + " manifest."); 1403 } 1404 1405 addPermissionGroupInfo(permissionGroupInfo); 1406 } 1407 PackageInfo packageInfo = generatePackageInfo(appPackage, flags); 1408 1409 packageInfo.applicationInfo.uid = Process.myUid(); 1410 packageInfo.applicationInfo.dataDir = createTempDir(packageInfo.packageName + "-dataDir"); 1411 installPackage(packageInfo); 1412 addFilters(activityFilters, appPackage.activities); 1413 addFilters(serviceFilters, appPackage.services); 1414 addFilters(providerFilters, appPackage.providers); 1415 addFilters(receiverFilters, appPackage.receivers); 1416 } 1417 generatePackageInfo(Package appPackage, int flags)1418 protected PackageInfo generatePackageInfo(Package appPackage, int flags) { 1419 1420 if (RuntimeEnvironment.getApiLevel() >= TIRAMISU) { 1421 return PackageParser.generatePackageInfo( 1422 appPackage, 1423 new int[] {0}, 1424 flags, 1425 0, 1426 0, 1427 Collections.emptySet(), 1428 FrameworkPackageUserState.DEFAULT, 1429 0); 1430 } else { 1431 return reflector(_PackageParser_.class) 1432 .generatePackageInfo(appPackage, new int[] {0}, flags, 0, 0); 1433 } 1434 } 1435 addFilters( Map<ComponentName, List<IntentFilter>> componentMap, List<? extends PackageParser.Component<?>> components)1436 private void addFilters( 1437 Map<ComponentName, List<IntentFilter>> componentMap, 1438 List<? extends PackageParser.Component<?>> components) { 1439 if (components == null) { 1440 return; 1441 } 1442 for (Component<?> component : components) { 1443 ComponentName componentName = component.getComponentName(); 1444 List<IntentFilter> registeredFilters = componentMap.get(componentName); 1445 if (registeredFilters == null) { 1446 registeredFilters = new ArrayList<>(); 1447 componentMap.put(componentName, registeredFilters); 1448 } 1449 for (IntentInfo intentInfo : component.intents) { 1450 registeredFilters.add(new IntentFilter(intentInfo)); 1451 } 1452 } 1453 } 1454 1455 public static class IntentComparator implements Comparator<Intent> { 1456 1457 @Override compare(Intent i1, Intent i2)1458 public int compare(Intent i1, Intent i2) { 1459 if (i1 == null && i2 == null) return 0; 1460 if (i1 == null && i2 != null) return -1; 1461 if (i1 != null && i2 == null) return 1; 1462 if (i1.equals(i2)) return 0; 1463 String action1 = i1.getAction(); 1464 String action2 = i2.getAction(); 1465 if (action1 == null && action2 != null) return -1; 1466 if (action1 != null && action2 == null) return 1; 1467 if (action1 != null && action2 != null) { 1468 if (!action1.equals(action2)) { 1469 return action1.compareTo(action2); 1470 } 1471 } 1472 Uri data1 = i1.getData(); 1473 Uri data2 = i2.getData(); 1474 if (data1 == null && data2 != null) return -1; 1475 if (data1 != null && data2 == null) return 1; 1476 if (data1 != null && data2 != null) { 1477 if (!data1.equals(data2)) { 1478 return data1.compareTo(data2); 1479 } 1480 } 1481 ComponentName component1 = i1.getComponent(); 1482 ComponentName component2 = i2.getComponent(); 1483 if (component1 == null && component2 != null) return -1; 1484 if (component1 != null && component2 == null) return 1; 1485 if (component1 != null && component2 != null) { 1486 if (!component1.equals(component2)) { 1487 return component1.compareTo(component2); 1488 } 1489 } 1490 String package1 = i1.getPackage(); 1491 String package2 = i2.getPackage(); 1492 if (package1 == null && package2 != null) return -1; 1493 if (package1 != null && package2 == null) return 1; 1494 if (package1 != null && package2 != null) { 1495 if (!package1.equals(package2)) { 1496 return package1.compareTo(package2); 1497 } 1498 } 1499 Set<String> categories1 = i1.getCategories(); 1500 Set<String> categories2 = i2.getCategories(); 1501 if (categories1 == null) return categories2 == null ? 0 : -1; 1502 if (categories2 == null) return 1; 1503 if (categories1.size() > categories2.size()) return 1; 1504 if (categories1.size() < categories2.size()) return -1; 1505 String[] array1 = categories1.toArray(new String[0]); 1506 String[] array2 = categories2.toArray(new String[0]); 1507 Arrays.sort(array1); 1508 Arrays.sort(array2); 1509 for (int i = 0; i < array1.length; ++i) { 1510 int val = array1[i].compareTo(array2[i]); 1511 if (val != 0) return val; 1512 } 1513 return 0; 1514 } 1515 } 1516 1517 /** 1518 * Compares {@link ResolveInfo}s, ordering better matches before worse ones. This is the order in 1519 * which resolve infos should be returned to the user. 1520 */ 1521 static class ResolveInfoComparator implements Comparator<ResolveInfo> { 1522 1523 @Override compare(ResolveInfo o1, ResolveInfo o2)1524 public int compare(ResolveInfo o1, ResolveInfo o2) { 1525 if (o1 == null && o2 == null) { 1526 return 0; 1527 } 1528 if (o1 == null) { 1529 return -1; 1530 } 1531 if (o2 == null) { 1532 return 1; 1533 } 1534 if (o1.preferredOrder != o2.preferredOrder) { 1535 // higher priority is before lower 1536 return -Integer.compare(o1.preferredOrder, o2.preferredOrder); 1537 } 1538 if (o1.priority != o2.priority) { 1539 // higher priority is before lower 1540 return -Integer.compare(o1.priority, o2.priority); 1541 } 1542 if (o1.match != o2.match) { 1543 // higher match is before lower 1544 return -Integer.compare(o1.match, o2.match); 1545 } 1546 return 0; 1547 } 1548 } 1549 1550 protected static class ComponentState { 1551 public int newState; 1552 public int flags; 1553 ComponentState(int newState, int flags)1554 public ComponentState(int newState, int flags) { 1555 this.newState = newState; 1556 this.flags = flags; 1557 } 1558 } 1559 1560 /** 1561 * Get list of intent filters defined for given activity. 1562 * 1563 * @param componentName Name of the activity whose intent filters are to be retrieved 1564 * @return the activity's intent filters 1565 * @throws IllegalArgumentException if component with given name doesn't exist. 1566 */ getIntentFiltersForActivity(ComponentName componentName)1567 public List<IntentFilter> getIntentFiltersForActivity(ComponentName componentName) { 1568 return getIntentFiltersForComponent(componentName, activityFilters); 1569 } 1570 1571 /** 1572 * Get list of intent filters defined for given service. 1573 * 1574 * @param componentName Name of the service whose intent filters are to be retrieved 1575 * @return the service's intent filters 1576 * @throws IllegalArgumentException if component with given name doesn't exist. 1577 */ getIntentFiltersForService(ComponentName componentName)1578 public List<IntentFilter> getIntentFiltersForService(ComponentName componentName) { 1579 return getIntentFiltersForComponent(componentName, serviceFilters); 1580 } 1581 1582 /** 1583 * Get list of intent filters defined for given receiver. 1584 * 1585 * @param componentName Name of the receiver whose intent filters are to be retrieved 1586 * @return the receiver's intent filters 1587 * @throws IllegalArgumentException if component with given name doesn't exist. 1588 */ getIntentFiltersForReceiver(ComponentName componentName)1589 public List<IntentFilter> getIntentFiltersForReceiver(ComponentName componentName) { 1590 return getIntentFiltersForComponent(componentName, receiverFilters); 1591 } 1592 1593 /** 1594 * Get list of intent filters defined for given provider. 1595 * 1596 * @param componentName Name of the provider whose intent filters are to be retrieved 1597 * @return the provider's intent filters 1598 * @throws IllegalArgumentException if component with given name doesn't exist. 1599 */ getIntentFiltersForProvider(ComponentName componentName)1600 public List<IntentFilter> getIntentFiltersForProvider(ComponentName componentName) { 1601 return getIntentFiltersForComponent(componentName, providerFilters); 1602 } 1603 1604 /** 1605 * Add intent filter for given activity. 1606 * 1607 * @throws IllegalArgumentException if component with given name doesn't exist. 1608 */ addIntentFilterForActivity(ComponentName componentName, IntentFilter filter)1609 public void addIntentFilterForActivity(ComponentName componentName, IntentFilter filter) { 1610 addIntentFilterForComponent(componentName, filter, activityFilters); 1611 } 1612 1613 /** 1614 * Add intent filter for given service. 1615 * 1616 * @throws IllegalArgumentException if component with given name doesn't exist. 1617 */ addIntentFilterForService(ComponentName componentName, IntentFilter filter)1618 public void addIntentFilterForService(ComponentName componentName, IntentFilter filter) { 1619 addIntentFilterForComponent(componentName, filter, serviceFilters); 1620 } 1621 1622 /** 1623 * Add intent filter for given receiver. 1624 * 1625 * @throws IllegalArgumentException if component with given name doesn't exist. 1626 */ addIntentFilterForReceiver(ComponentName componentName, IntentFilter filter)1627 public void addIntentFilterForReceiver(ComponentName componentName, IntentFilter filter) { 1628 addIntentFilterForComponent(componentName, filter, receiverFilters); 1629 } 1630 1631 /** 1632 * Add intent filter for given provider. 1633 * 1634 * @throws IllegalArgumentException if component with given name doesn't exist. 1635 */ addIntentFilterForProvider(ComponentName componentName, IntentFilter filter)1636 public void addIntentFilterForProvider(ComponentName componentName, IntentFilter filter) { 1637 addIntentFilterForComponent(componentName, filter, providerFilters); 1638 } 1639 1640 /** 1641 * Clears intent filters for given activity. 1642 * 1643 * @throws IllegalArgumentException if component with given name doesn't exist. 1644 */ clearIntentFilterForActivity(ComponentName componentName)1645 public void clearIntentFilterForActivity(ComponentName componentName) { 1646 clearIntentFilterForComponent(componentName, activityFilters); 1647 } 1648 1649 /** 1650 * Clears intent filters for given service. 1651 * 1652 * @throws IllegalArgumentException if component with given name doesn't exist. 1653 */ clearIntentFilterForService(ComponentName componentName)1654 public void clearIntentFilterForService(ComponentName componentName) { 1655 clearIntentFilterForComponent(componentName, serviceFilters); 1656 } 1657 1658 /** 1659 * Clears intent filters for given receiver. 1660 * 1661 * @throws IllegalArgumentException if component with given name doesn't exist. 1662 */ clearIntentFilterForReceiver(ComponentName componentName)1663 public void clearIntentFilterForReceiver(ComponentName componentName) { 1664 clearIntentFilterForComponent(componentName, receiverFilters); 1665 } 1666 1667 /** 1668 * Clears intent filters for given provider. 1669 * 1670 * @throws IllegalArgumentException if component with given name doesn't exist. 1671 */ clearIntentFilterForProvider(ComponentName componentName)1672 public void clearIntentFilterForProvider(ComponentName componentName) { 1673 clearIntentFilterForComponent(componentName, providerFilters); 1674 } 1675 addIntentFilterForComponent( ComponentName componentName, IntentFilter filter, Map<ComponentName, List<IntentFilter>> filterMap)1676 private void addIntentFilterForComponent( 1677 ComponentName componentName, 1678 IntentFilter filter, 1679 Map<ComponentName, List<IntentFilter>> filterMap) { 1680 // Existing components should have an entry in respective filterMap. 1681 // It is OK to search over all filter maps, as it is impossible to have the same component name 1682 // being of two comopnent types (like activity and service at the same time). 1683 List<IntentFilter> filters = filterMap.get(componentName); 1684 if (filters != null) { 1685 filters.add(filter); 1686 return; 1687 } 1688 throw new IllegalArgumentException(componentName + " doesn't exist"); 1689 } 1690 clearIntentFilterForComponent( ComponentName componentName, Map<ComponentName, List<IntentFilter>> filterMap)1691 private void clearIntentFilterForComponent( 1692 ComponentName componentName, Map<ComponentName, List<IntentFilter>> filterMap) { 1693 List<IntentFilter> filters = filterMap.get(componentName); 1694 if (filters != null) { 1695 filters.clear(); 1696 return; 1697 } 1698 throw new IllegalArgumentException(componentName + " doesn't exist"); 1699 } 1700 getIntentFiltersForComponent( ComponentName componentName, Map<ComponentName, List<IntentFilter>> filterMap)1701 private List<IntentFilter> getIntentFiltersForComponent( 1702 ComponentName componentName, Map<ComponentName, List<IntentFilter>> filterMap) { 1703 List<IntentFilter> filters = filterMap.get(componentName); 1704 if (filters != null) { 1705 return new ArrayList<>(filters); 1706 } 1707 throw new IllegalArgumentException(componentName + " doesn't exist"); 1708 } 1709 1710 /** 1711 * Method to retrieve persistent preferred activities as set by {@link 1712 * android.app.admin.DevicePolicyManager#addPersistentPreferredActivity}. 1713 * 1714 * <p>Works the same way as analogous {@link PackageManager#getPreferredActivities} for regular 1715 * preferred activities. 1716 */ getPersistentPreferredActivities( List<IntentFilter> outFilters, List<ComponentName> outActivities, String packageName)1717 public int getPersistentPreferredActivities( 1718 List<IntentFilter> outFilters, List<ComponentName> outActivities, String packageName) { 1719 return getPreferredActivitiesInternal( 1720 outFilters, outActivities, packageName, persistentPreferredActivities); 1721 } 1722 getPreferredActivitiesInternal( List<IntentFilter> outFilters, List<ComponentName> outActivities, String packageName, SortedMap<ComponentName, List<IntentFilter>> preferredActivitiesMap)1723 protected static int getPreferredActivitiesInternal( 1724 List<IntentFilter> outFilters, 1725 List<ComponentName> outActivities, 1726 String packageName, 1727 SortedMap<ComponentName, List<IntentFilter>> preferredActivitiesMap) { 1728 SortedMap<ComponentName, List<IntentFilter>> preferredMap = preferredActivitiesMap; 1729 if (packageName != null) { 1730 preferredMap = mapForPackage(preferredActivitiesMap, packageName); 1731 } 1732 int result = 0; 1733 for (Entry<ComponentName, List<IntentFilter>> entry : preferredMap.entrySet()) { 1734 int filterCount = entry.getValue().size(); 1735 result += filterCount; 1736 ComponentName[] componentNames = new ComponentName[filterCount]; 1737 Arrays.fill(componentNames, entry.getKey()); 1738 outActivities.addAll(asList(componentNames)); 1739 outFilters.addAll(entry.getValue()); 1740 } 1741 1742 return result; 1743 } 1744 clearPackagePersistentPreferredActivities(String packageName)1745 void clearPackagePersistentPreferredActivities(String packageName) { 1746 clearPackagePreferredActivitiesInternal(packageName, persistentPreferredActivities); 1747 } 1748 clearPackagePreferredActivitiesInternal( String packageName, SortedMap<ComponentName, List<IntentFilter>> preferredActivitiesMap)1749 protected static void clearPackagePreferredActivitiesInternal( 1750 String packageName, SortedMap<ComponentName, List<IntentFilter>> preferredActivitiesMap) { 1751 mapForPackage(preferredActivitiesMap, packageName).clear(); 1752 } 1753 addPersistentPreferredActivity(IntentFilter filter, ComponentName activity)1754 void addPersistentPreferredActivity(IntentFilter filter, ComponentName activity) { 1755 addPreferredActivityInternal(filter, activity, persistentPreferredActivities); 1756 } 1757 addPreferredActivityInternal( IntentFilter filter, ComponentName activity, SortedMap<ComponentName, List<IntentFilter>> preferredActivitiesMap)1758 protected static void addPreferredActivityInternal( 1759 IntentFilter filter, 1760 ComponentName activity, 1761 SortedMap<ComponentName, List<IntentFilter>> preferredActivitiesMap) { 1762 List<IntentFilter> filters = preferredActivitiesMap.get(activity); 1763 if (filters == null) { 1764 filters = new ArrayList<>(); 1765 preferredActivitiesMap.put(activity, filters); 1766 } 1767 filters.add(filter); 1768 } 1769 mapForPackage( SortedMap<ComponentName, V> input, @Nullable String packageName)1770 protected static <V> SortedMap<ComponentName, V> mapForPackage( 1771 SortedMap<ComponentName, V> input, @Nullable String packageName) { 1772 if (packageName == null) { 1773 return input; 1774 } 1775 return input.subMap( 1776 new ComponentName(packageName, ""), new ComponentName(packageName + " ", "")); 1777 } 1778 isComponentEnabled(@ullable ComponentInfo componentInfo)1779 static boolean isComponentEnabled(@Nullable ComponentInfo componentInfo) { 1780 if (componentInfo == null) { 1781 return true; 1782 } 1783 if (componentInfo.applicationInfo == null 1784 || componentInfo.applicationInfo.packageName == null 1785 || componentInfo.name == null) { 1786 return componentInfo.enabled; 1787 } 1788 ComponentName name = 1789 new ComponentName(componentInfo.applicationInfo.packageName, componentInfo.name); 1790 ComponentState componentState = componentList.get(name); 1791 if (componentState == null 1792 || componentState.newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { 1793 return componentInfo.enabled; 1794 } 1795 return componentState.newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED; 1796 } 1797 1798 /** 1799 * Returns the current {@link PackageSetting} of {@code packageName}. 1800 * 1801 * <p>If {@code packageName} is not present in this {@link ShadowPackageManager}, this method will 1802 * return null. 1803 */ getPackageSetting(String packageName)1804 public PackageSetting getPackageSetting(String packageName) { 1805 PackageSetting setting = packageSettings.get(packageName); 1806 return setting == null ? null : new PackageSetting(setting); 1807 } 1808 1809 /** 1810 * If this method has been called with true, then in cases where many activities match a filter, 1811 * an activity chooser will be resolved instead of just the first pick. 1812 */ setShouldShowActivityChooser(boolean shouldShowActivityChooser)1813 public void setShouldShowActivityChooser(boolean shouldShowActivityChooser) { 1814 this.shouldShowActivityChooser = shouldShowActivityChooser; 1815 } 1816 1817 /** Set value to be returned by {@link PackageManager#isSafeMode}. */ setSafeMode(boolean safeMode)1818 public void setSafeMode(boolean safeMode) { 1819 ShadowPackageManager.safeMode = safeMode; 1820 } 1821 1822 /** 1823 * Returns the last value provided to {@code setDistractingPackageRestrictions} for {@code pkg}. 1824 * 1825 * <p>Defaults to {@code PackageManager.RESTRICTION_NONE} if {@code 1826 * setDistractingPackageRestrictions} has not been called for {@code pkg}. 1827 */ getDistractingPackageRestrictions(String pkg)1828 public int getDistractingPackageRestrictions(String pkg) { 1829 return distractingPackageRestrictions.getOrDefault(pkg, PackageManager.RESTRICTION_NONE); 1830 } 1831 1832 /** 1833 * Adds a String resource with {@code resId} corresponding to {@code packageName}. This is 1834 * retrieved in shadow implementation of {@link PackageManager#getText(String, int, 1835 * ApplicationInfo)}. 1836 */ addStringResource(String packageName, int resId, String text)1837 public void addStringResource(String packageName, int resId, String text) { 1838 if (!stringResources.containsKey(packageName)) { 1839 stringResources.put(packageName, new HashMap<>()); 1840 } 1841 1842 stringResources.get(packageName).put(resId, text); 1843 } 1844 1845 /** Set value to be returned by {@link PackageManager#isAutoRevokeWhitelisted}. */ setAutoRevokeWhitelisted(boolean whitelisted)1846 public void setAutoRevokeWhitelisted(boolean whitelisted) { 1847 ShadowPackageManager.whitelisted = whitelisted; 1848 } 1849 1850 @Resetter reset()1851 public static void reset() { 1852 synchronized (lock) { 1853 permissionRationaleMap.clear(); 1854 systemAvailableFeatures.clear(); 1855 systemSharedLibraryNames.clear(); 1856 packageInfos.clear(); 1857 packageArchiveInfo.clear(); 1858 packageStatsMap.clear(); 1859 packageInstallerMap.clear(); 1860 packageInstallSourceInfoMap.clear(); 1861 packagesForUid.clear(); 1862 uidForPackage.clear(); 1863 namesForUid.clear(); 1864 verificationResults.clear(); 1865 verificationTimeoutExtension.clear(); 1866 verificationCodeAtTimeoutExtension.clear(); 1867 currentToCanonicalNames.clear(); 1868 canonicalToCurrentNames.clear(); 1869 componentList.clear(); 1870 drawableList.clear(); 1871 applicationIcons.clear(); 1872 unbadgedApplicationIcons.clear(); 1873 systemFeatureList.clear(); 1874 systemFeatureList.putAll(SystemFeatureListInitializer.getSystemFeatures()); 1875 preferredActivities.clear(); 1876 persistentPreferredActivities.clear(); 1877 drawables.clear(); 1878 stringResources.clear(); 1879 applicationEnabledSettingMap.clear(); 1880 extraPermissions.clear(); 1881 permissionGroups.clear(); 1882 permissionFlags.clear(); 1883 resources.clear(); 1884 resolveInfoForIntent.clear(); 1885 deletedPackages.clear(); 1886 pendingDeleteCallbacks.clear(); 1887 hiddenPackages.clear(); 1888 sequenceNumberChangedPackagesMap.clear(); 1889 activityFilters.clear(); 1890 serviceFilters.clear(); 1891 providerFilters.clear(); 1892 receiverFilters.clear(); 1893 packageSettings.clear(); 1894 safeMode = false; 1895 whitelisted = false; 1896 } 1897 } 1898 1899 @ForType(PackageManager.class) 1900 interface PackageManagerReflector { 1901 1902 @Direct getPackageArchiveInfo(String archiveFilePath, int flags)1903 PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags); 1904 } 1905 } 1906