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