• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.shadows;
2 
3 import static android.content.IntentFilter.MATCH_CATEGORY_MASK;
4 import static android.content.pm.ApplicationInfo.FLAG_INSTALLED;
5 import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
6 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
7 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
8 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
9 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
10 import static android.content.pm.PackageManager.DONT_KILL_APP;
11 import static android.content.pm.PackageManager.GET_ACTIVITIES;
12 import static android.content.pm.PackageManager.GET_META_DATA;
13 import static android.content.pm.PackageManager.GET_PROVIDERS;
14 import static android.content.pm.PackageManager.GET_RECEIVERS;
15 import static android.content.pm.PackageManager.GET_RESOLVED_FILTER;
16 import static android.content.pm.PackageManager.GET_SERVICES;
17 import static android.content.pm.PackageManager.GET_SIGNATURES;
18 import static android.content.pm.PackageManager.GET_SIGNING_CERTIFICATES;
19 import static android.content.pm.PackageManager.MATCH_ALL;
20 import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
21 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
22 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
23 import static android.content.pm.PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
24 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1;
25 import static android.os.Build.VERSION_CODES.M;
26 import static android.os.Build.VERSION_CODES.N;
27 import static android.os.Build.VERSION_CODES.O;
28 import static android.os.Build.VERSION_CODES.O_MR1;
29 import static android.os.Build.VERSION_CODES.P;
30 import static android.os.Build.VERSION_CODES.Q;
31 import static android.os.Build.VERSION_CODES.R;
32 import static android.os.Build.VERSION_CODES.S;
33 import static android.os.Build.VERSION_CODES.S_V2;
34 import static android.os.Build.VERSION_CODES.TIRAMISU;
35 import static com.google.common.base.Preconditions.checkNotNull;
36 import static org.robolectric.annotation.GetInstallerPackageNameMode.Mode.REALISTIC;
37 import static org.robolectric.util.reflector.Reflector.reflector;
38 
39 import android.Manifest.permission;
40 import android.annotation.DrawableRes;
41 import android.annotation.NonNull;
42 import android.annotation.Nullable;
43 import android.annotation.RequiresPermission;
44 import android.annotation.StringRes;
45 import android.annotation.UserIdInt;
46 import android.app.ApplicationPackageManager;
47 import android.app.admin.DevicePolicyManager;
48 import android.content.ComponentName;
49 import android.content.Context;
50 import android.content.Intent;
51 import android.content.IntentFilter;
52 import android.content.IntentSender;
53 import android.content.pm.ActivityInfo;
54 import android.content.pm.ApplicationInfo;
55 import android.content.pm.ChangedPackages;
56 import android.content.pm.ComponentInfo;
57 import android.content.pm.FeatureInfo;
58 import android.content.pm.IPackageDataObserver;
59 import android.content.pm.IPackageDeleteObserver;
60 import android.content.pm.IPackageStatsObserver;
61 import android.content.pm.InstrumentationInfo;
62 import android.content.pm.IntentFilterVerificationInfo;
63 import android.content.pm.ModuleInfo;
64 import android.content.pm.PackageInfo;
65 import android.content.pm.PackageItemInfo;
66 import android.content.pm.PackageManager;
67 import android.content.pm.PackageManager.ComponentEnabledSetting;
68 import android.content.pm.PackageManager.ComponentInfoFlags;
69 import android.content.pm.PackageManager.NameNotFoundException;
70 import android.content.pm.PackageManager.OnPermissionsChangedListener;
71 import android.content.pm.PackageManager.PackageInfoFlags;
72 import android.content.pm.PackageManager.ResolveInfoFlags;
73 import android.content.pm.PackageStats;
74 import android.content.pm.PermissionGroupInfo;
75 import android.content.pm.PermissionInfo;
76 import android.content.pm.ProviderInfo;
77 import android.content.pm.ResolveInfo;
78 import android.content.pm.ServiceInfo;
79 import android.content.pm.Signature;
80 import android.content.pm.VerifierDeviceIdentity;
81 import android.content.res.AssetManager;
82 import android.content.res.Resources;
83 import android.graphics.drawable.Drawable;
84 import android.net.Uri;
85 import android.os.Build;
86 import android.os.Build.VERSION;
87 import android.os.Build.VERSION_CODES;
88 import android.os.Handler;
89 import android.os.Looper;
90 import android.os.Parcel;
91 import android.os.PersistableBundle;
92 import android.os.RemoteException;
93 import android.os.UserHandle;
94 import android.os.storage.VolumeInfo;
95 import android.telecom.TelecomManager;
96 import android.util.Log;
97 import android.util.Pair;
98 import com.google.common.base.Function;
99 import com.google.common.base.Preconditions;
100 import com.google.common.base.Splitter;
101 import com.google.common.collect.ImmutableList;
102 import com.google.common.collect.Sets;
103 import java.io.File;
104 import java.util.ArrayList;
105 import java.util.Arrays;
106 import java.util.Collections;
107 import java.util.HashMap;
108 import java.util.HashSet;
109 import java.util.Iterator;
110 import java.util.List;
111 import java.util.Map;
112 import java.util.Objects;
113 import java.util.Set;
114 import java.util.SortedMap;
115 import java.util.concurrent.Executor;
116 import java.util.function.BiConsumer;
117 import java.util.function.Consumer;
118 import org.robolectric.RuntimeEnvironment;
119 import org.robolectric.annotation.GetInstallerPackageNameMode;
120 import org.robolectric.annotation.HiddenApi;
121 import org.robolectric.annotation.Implementation;
122 import org.robolectric.annotation.Implements;
123 import org.robolectric.annotation.RealObject;
124 import org.robolectric.config.ConfigurationRegistry;
125 import org.robolectric.util.reflector.Accessor;
126 import org.robolectric.util.reflector.Direct;
127 import org.robolectric.util.reflector.ForType;
128 
129 @Implements(value = ApplicationPackageManager.class, isInAndroidSdk = false, looseSignatures = true)
130 public class ShadowApplicationPackageManager extends ShadowPackageManager {
131   /** Package name of the Android platform. */
132   private static final String PLATFORM_PACKAGE_NAME = "android";
133 
134   /** MIME type of Android Packages (APKs). */
135   private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
136 
137   /** {@link Uri} scheme of installed apps. */
138   private static final String PACKAGE_SCHEME = "package";
139 
140   @RealObject private ApplicationPackageManager realObject;
141   private final List<String> clearedApplicationUserDataPackages = new ArrayList<>();
142   // A map of UserIDs to default browsers.
143   private final HashMap<Integer, String> defaultBrowsers = new HashMap<>();
144 
145   @Implementation
getInstalledPackages(int flags)146   public List<PackageInfo> getInstalledPackages(int flags) {
147     return getInstalledPackages((long) flags);
148   }
149 
150   @Implementation(minSdk = TIRAMISU)
getInstalledPackages(Object flags)151   protected List<PackageInfo> getInstalledPackages(Object flags) {
152     return getInstalledPackages(((PackageInfoFlags) flags).getValue());
153   }
154 
getInstalledPackages(long flags)155   private List<PackageInfo> getInstalledPackages(long flags) {
156     List<PackageInfo> result = new ArrayList<>();
157     synchronized (lock) {
158       Set<String> packageNames = null;
159       if ((flags & MATCH_UNINSTALLED_PACKAGES) == 0) {
160         packageNames = packageInfos.keySet();
161       } else {
162         packageNames = Sets.union(packageInfos.keySet(), deletedPackages);
163       }
164       for (String packageName : packageNames) {
165         try {
166           PackageInfo packageInfo = getPackageInfo(packageName, flags);
167           result.add(packageInfo);
168         } catch (NameNotFoundException e) {
169           Log.i(TAG, String.format("Package %s filtered out: %s", packageName, e.getMessage()));
170         }
171       }
172     }
173     return result;
174   }
175 
176   @Implementation(minSdk = Q)
getInstalledModules(int flags)177   protected List<ModuleInfo> getInstalledModules(int flags) {
178     synchronized (lock) {
179       List<ModuleInfo> result = new ArrayList<>();
180       for (String moduleName : moduleInfos.keySet()) {
181         try {
182           ModuleInfo moduleInfo = (ModuleInfo) getModuleInfo(moduleName, flags);
183           result.add(moduleInfo);
184         } catch (NameNotFoundException e) {
185           Log.i(TAG, String.format("Module %s filtered out: %s", moduleName, e.getMessage()));
186         }
187       }
188       return result;
189     }
190   }
191 
192   @Implementation(minSdk = Q)
getModuleInfo(String packageName, int flags)193   protected Object getModuleInfo(String packageName, int flags) throws NameNotFoundException {
194     synchronized (lock) {
195       // Double checks that the respective package matches and is not disabled
196       getPackageInfo(packageName, flags);
197       Object info = moduleInfos.get(packageName);
198       if (info == null) {
199         throw new NameNotFoundException("Module: " + packageName + " is not installed.");
200       }
201 
202       return info;
203     }
204   }
205 
206   @Implementation
getActivityInfo(ComponentName component, int flags)207   protected ActivityInfo getActivityInfo(ComponentName component, int flags)
208       throws NameNotFoundException {
209     return getComponentInfo(
210         component,
211         flags,
212         packageInfo -> packageInfo.activities,
213         resolveInfo -> resolveInfo.activityInfo,
214         ActivityInfo::new);
215   }
216 
getComponentInfo( ComponentName component, int flags, Function<PackageInfo, T[]> componentsInPackage, Function<ResolveInfo, T> componentInResolveInfo, Function<T, T> copyConstructor)217   private <T extends ComponentInfo> T getComponentInfo(
218       ComponentName component,
219       int flags,
220       Function<PackageInfo, T[]> componentsInPackage,
221       Function<ResolveInfo, T> componentInResolveInfo,
222       Function<T, T> copyConstructor)
223       throws NameNotFoundException {
224     String activityName = component.getClassName();
225     String packageName = component.getPackageName();
226     PackageInfo packageInfo = getInternalMutablePackageInfo(packageName);
227     T result = null;
228     ApplicationInfo appInfo = null;
229     // search in the manifest
230     if (packageInfo != null) {
231       if (packageInfo.applicationInfo != null) {
232         appInfo = packageInfo.applicationInfo;
233       }
234       T[] components = componentsInPackage.apply(packageInfo);
235       if (components != null) {
236         for (T activity : components) {
237           if (activityName.equals(activity.name)) {
238             result = copyConstructor.apply(activity);
239             break;
240           }
241         }
242       }
243     }
244     if (result == null) {
245       // look in the registered intents
246       outer:
247       for (List<ResolveInfo> listOfResolveInfo : resolveInfoForIntent.values()) {
248         for (ResolveInfo resolveInfo : listOfResolveInfo) {
249           T info = componentInResolveInfo.apply(resolveInfo);
250           if (isValidComponentInfo(info)
251               && component.equals(new ComponentName(info.applicationInfo.packageName, info.name))) {
252             result = copyConstructor.apply(info);
253             if (appInfo == null) {
254               // we found valid app info in the resolve info. Use it.
255               appInfo = result.applicationInfo;
256             }
257             break outer;
258           }
259         }
260       }
261     }
262     if (result == null) {
263       throw new NameNotFoundException("Component not found: " + component);
264     }
265     if (appInfo == null) {
266       appInfo = new ApplicationInfo();
267       appInfo.packageName = packageName;
268       appInfo.flags = ApplicationInfo.FLAG_INSTALLED;
269     } else {
270       appInfo = new ApplicationInfo(appInfo);
271     }
272     result.applicationInfo = appInfo;
273     applyFlagsToComponentInfo(result, flags);
274     return result;
275   }
276 
277   @Implementation
hasSystemFeature(String name)278   protected boolean hasSystemFeature(String name) {
279     return systemFeatureList.containsKey(name) ? systemFeatureList.get(name) : false;
280   }
281 
282   @Implementation
getComponentEnabledSetting(ComponentName componentName)283   protected int getComponentEnabledSetting(ComponentName componentName) {
284     ComponentState state = componentList.get(componentName);
285     return state != null ? state.newState : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
286   }
287 
288   @Implementation
getNameForUid(int uid)289   protected @Nullable String getNameForUid(int uid) {
290     return namesForUid.get(uid);
291   }
292 
293   @Implementation
294   @Override
getPackagesForUid(int uid)295   protected @Nullable String[] getPackagesForUid(int uid) {
296     String[] packageNames = packagesForUid.get(uid);
297     if (packageNames != null) {
298       return packageNames;
299     }
300 
301     Set<String> results = new HashSet<>();
302     synchronized (lock) {
303       for (PackageInfo packageInfo : packageInfos.values()) {
304         if (packageInfo.applicationInfo != null && packageInfo.applicationInfo.uid == uid) {
305           results.add(packageInfo.packageName);
306         }
307       }
308     }
309 
310     return results.isEmpty() ? null : results.toArray(new String[results.size()]);
311   }
312 
313   @Implementation
getApplicationEnabledSetting(String packageName)314   protected int getApplicationEnabledSetting(String packageName) {
315     synchronized (lock) {
316       if (!packageInfos.containsKey(packageName)) {
317         throw new IllegalArgumentException("Package doesn't exist: " + packageName);
318       }
319     }
320 
321     return applicationEnabledSettingMap.get(packageName);
322   }
323 
324   @Implementation
getProviderInfo(ComponentName component, int flags)325   protected ProviderInfo getProviderInfo(ComponentName component, int flags)
326       throws NameNotFoundException {
327     return getComponentInfo(
328         component,
329         flags,
330         packageInfo -> packageInfo.providers,
331         resolveInfo -> resolveInfo.providerInfo,
332         ProviderInfo::new);
333   }
334 
335   @Implementation
setComponentEnabledSetting(ComponentName componentName, int newState, int flags)336   protected void setComponentEnabledSetting(ComponentName componentName, int newState, int flags) {
337     componentList.put(componentName, new ComponentState(newState, flags));
338   }
339 
340   @Implementation(minSdk = TIRAMISU)
setComponentEnabledSettings(List<ComponentEnabledSetting> settings)341   protected void setComponentEnabledSettings(List<ComponentEnabledSetting> settings) {
342     for (ComponentEnabledSetting setting : settings) {
343       componentList.put(
344           setting.getComponentName(),
345           new ComponentState(setting.getEnabledState(), setting.getEnabledFlags()));
346     }
347   }
348 
349   @Implementation(minSdk = Q)
setSyntheticAppDetailsActivityEnabled(String packageName, boolean enabled)350   protected void setSyntheticAppDetailsActivityEnabled(String packageName, boolean enabled) {
351     ComponentName componentName =
352         new ComponentName(packageName, PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME);
353     setComponentEnabledSetting(
354         componentName,
355         enabled ? COMPONENT_ENABLED_STATE_DEFAULT : COMPONENT_ENABLED_STATE_DISABLED,
356         DONT_KILL_APP);
357   }
358 
359   @Implementation(minSdk = Q)
getSyntheticAppDetailsActivityEnabled(String packageName)360   protected boolean getSyntheticAppDetailsActivityEnabled(String packageName) {
361     ComponentName componentName =
362         new ComponentName(packageName, PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME);
363     int state = getComponentEnabledSetting(componentName);
364     return state == COMPONENT_ENABLED_STATE_ENABLED || state == COMPONENT_ENABLED_STATE_DEFAULT;
365   }
366 
367   @Implementation
setApplicationEnabledSetting(String packageName, int newState, int flags)368   protected void setApplicationEnabledSetting(String packageName, int newState, int flags) {
369     applicationEnabledSettingMap.put(packageName, newState);
370   }
371 
372   @Implementation
resolveActivity(Intent intent, int flags)373   protected ResolveInfo resolveActivity(Intent intent, int flags) {
374     List<ResolveInfo> candidates = queryIntentActivities(intent, flags);
375     if (candidates.isEmpty()) {
376       return null;
377     }
378     if (candidates.size() == 1) {
379       return candidates.get(0);
380     }
381     ResolveInfo persistentPreferredResolveInfo =
382         resolvePreferredActivity(intent, candidates, persistentPreferredActivities);
383     if (persistentPreferredResolveInfo != null) {
384       return persistentPreferredResolveInfo;
385     }
386     ResolveInfo preferredResolveInfo =
387         resolvePreferredActivity(intent, candidates, preferredActivities);
388     if (preferredResolveInfo != null) {
389       return preferredResolveInfo;
390     }
391     if (!shouldShowActivityChooser) {
392       return candidates.get(0);
393     }
394     ResolveInfo c1 = candidates.get(0);
395     ResolveInfo c2 = candidates.get(1);
396     if (c1.preferredOrder == c2.preferredOrder
397         && isValidComponentInfo(c1.activityInfo)
398         && isValidComponentInfo(c2.activityInfo)) {
399       // When the top pick is as good as the second and is not preferred explicitly show the
400       // chooser
401       ResolveInfo result = new ResolveInfo();
402       result.activityInfo = new ActivityInfo();
403       result.activityInfo.name = "ActivityResolver";
404       result.activityInfo.packageName = "android";
405       result.activityInfo.applicationInfo = new ApplicationInfo();
406       result.activityInfo.applicationInfo.flags = FLAG_INSTALLED | FLAG_SYSTEM;
407       result.activityInfo.applicationInfo.packageName = "android";
408       return result;
409     } else {
410       return c1;
411     }
412   }
413 
resolvePreferredActivity( Intent intent, List<ResolveInfo> candidates, SortedMap<ComponentName, List<IntentFilter>> preferredActivities)414   private ResolveInfo resolvePreferredActivity(
415       Intent intent,
416       List<ResolveInfo> candidates,
417       SortedMap<ComponentName, List<IntentFilter>> preferredActivities) {
418     preferredActivities = mapForPackage(preferredActivities, intent.getPackage());
419     for (ResolveInfo candidate : candidates) {
420       ActivityInfo activityInfo = candidate.activityInfo;
421       if (!isValidComponentInfo(activityInfo)) {
422         continue;
423       }
424       ComponentName candidateName =
425           new ComponentName(activityInfo.applicationInfo.packageName, activityInfo.name);
426       List<IntentFilter> intentFilters = preferredActivities.get(candidateName);
427       if (intentFilters == null) {
428         continue;
429       }
430       for (IntentFilter filter : intentFilters) {
431         if ((filter.match(getContext().getContentResolver(), intent, false, "robo")
432                 & MATCH_CATEGORY_MASK)
433             != 0) {
434           return candidate;
435         }
436       }
437     }
438     return null;
439   }
440 
441   @Implementation
resolveContentProvider(String name, int flags)442   protected ProviderInfo resolveContentProvider(String name, int flags) {
443     if (name == null) {
444       return null;
445     }
446     synchronized (lock) {
447       for (PackageInfo packageInfo : packageInfos.values()) {
448         if (packageInfo.providers == null) {
449           continue;
450         }
451 
452         for (ProviderInfo providerInfo : packageInfo.providers) {
453           for (String authority : Splitter.on(';').split(providerInfo.authority)) {
454             if (name.equals(authority)) {
455               return new ProviderInfo(providerInfo);
456             }
457           }
458         }
459       }
460     }
461     return null;
462   }
463 
464   @Implementation
resolveContentProviderAsUser( String name, int flags, @UserIdInt int userId)465   protected ProviderInfo resolveContentProviderAsUser(
466       String name, int flags, @UserIdInt int userId) {
467     return null;
468   }
469 
470   @Implementation
getPackageInfo(String packageName, int flags)471   protected PackageInfo getPackageInfo(String packageName, int flags) throws NameNotFoundException {
472     return getPackageInfo(packageName, (long) flags);
473   }
474 
475   @Implementation(minSdk = TIRAMISU)
getPackageInfo(Object packageName, Object flags)476   protected PackageInfo getPackageInfo(Object packageName, Object flags)
477       throws NameNotFoundException {
478     return getPackageInfo((String) packageName, ((PackageInfoFlags) flags).getValue());
479   }
480 
getPackageInfo(String packageName, long flags)481   private PackageInfo getPackageInfo(String packageName, long flags) throws NameNotFoundException {
482     synchronized (lock) {
483       PackageInfo info = packageInfos.get(packageName);
484       if (info == null
485           && (flags & MATCH_UNINSTALLED_PACKAGES) != 0
486           && deletedPackages.contains(packageName)) {
487         info = new PackageInfo();
488         info.packageName = packageName;
489         info.applicationInfo = new ApplicationInfo();
490         info.applicationInfo.packageName = packageName;
491       }
492       if (info == null) {
493         throw new NameNotFoundException(packageName);
494       }
495       info = newPackageInfo(info);
496       if (info.applicationInfo == null) {
497         return info;
498       }
499       if (hiddenPackages.contains(packageName) && !isFlagSet(flags, MATCH_UNINSTALLED_PACKAGES)) {
500         throw new NameNotFoundException("Package is hidden, can't find");
501       }
502       applyFlagsToApplicationInfo(info.applicationInfo, flags);
503       info.activities =
504           applyFlagsToComponentInfoList(info.activities, flags, GET_ACTIVITIES, ActivityInfo::new);
505       info.services =
506           applyFlagsToComponentInfoList(info.services, flags, GET_SERVICES, ServiceInfo::new);
507       info.receivers =
508           applyFlagsToComponentInfoList(info.receivers, flags, GET_RECEIVERS, ActivityInfo::new);
509       info.providers =
510           applyFlagsToComponentInfoList(info.providers, flags, GET_PROVIDERS, ProviderInfo::new);
511       return info;
512     }
513   }
514 
515   /**
516    * Starting in Android S, this method was moved from {@link android.content.pm.PackageManager} to
517    * {@link ApplicationPackageManager}. However, it was moved back to {@link
518    * android.content.pm.PackageManager} in T.
519    */
520   @Override
521   @Implementation(minSdk = S, maxSdk = S_V2)
getPackageArchiveInfo(String archiveFilePath, int flags)522   protected PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) {
523     int apiLevel = RuntimeEnvironment.getApiLevel();
524     if (apiLevel == S || apiLevel == S_V2) {
525 
526       PackageInfo shadowPackageInfo = getShadowPackageArchiveInfo(archiveFilePath, flags);
527       if (shadowPackageInfo != null) {
528         return shadowPackageInfo;
529       } else {
530         return reflector(ReflectorApplicationPackageManager.class, realObject)
531             .getPackageArchiveInfo(archiveFilePath, flags);
532       }
533     } else {
534       return super.getPackageArchiveInfo(archiveFilePath, flags);
535     }
536   }
537 
538   // There is no copy constructor for PackageInfo
newPackageInfo(PackageInfo orig)539   private static PackageInfo newPackageInfo(PackageInfo orig) {
540     Parcel parcel = Parcel.obtain();
541     orig.writeToParcel(parcel, 0);
542     parcel.setDataPosition(0);
543     return PackageInfo.CREATOR.createFromParcel(parcel);
544   }
545 
applyFlagsToComponentInfoList( T[] components, long flags, int activationFlag, Function<T, T> copyConstructor)546   private <T extends ComponentInfo> T[] applyFlagsToComponentInfoList(
547       T[] components, long flags, int activationFlag, Function<T, T> copyConstructor) {
548     if (components == null || (flags & activationFlag) == 0) {
549       return null;
550     }
551     List<T> returned = new ArrayList<>(components.length);
552     for (T component : components) {
553       component = copyConstructor.apply(component);
554       try {
555         applyFlagsToComponentInfo(component, flags);
556         returned.add(component);
557       } catch (NameNotFoundException e) {
558         // skip this component
559       }
560     }
561     if (returned.isEmpty()) {
562       return null;
563     }
564     @SuppressWarnings("unchecked") // component arrays are of their respective types.
565     Class<T[]> componentArrayType = (Class<T[]>) components.getClass();
566     T[] result = Arrays.copyOf(components, returned.size(), componentArrayType);
567     return returned.toArray(result);
568   }
569 
570   @Implementation
queryIntentServices(Intent intent, int flags)571   protected List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
572     return queryIntentComponents(
573         intent,
574         flags,
575         (pkg) -> pkg.services,
576         serviceFilters,
577         (resolveInfo, serviceInfo) -> resolveInfo.serviceInfo = serviceInfo,
578         (resolveInfo) -> resolveInfo.serviceInfo,
579         ServiceInfo::new);
580   }
581 
hasSomeComponentInfo(ResolveInfo resolveInfo)582   private boolean hasSomeComponentInfo(ResolveInfo resolveInfo) {
583 
584     return resolveInfo.activityInfo != null
585         || resolveInfo.serviceInfo != null
586         || resolveInfo.providerInfo != null;
587   }
588 
isFlagSet(long flags, long matchFlag)589   private static boolean isFlagSet(long flags, long matchFlag) {
590     return (flags & matchFlag) == matchFlag;
591   }
592 
isValidComponentInfo(ComponentInfo componentInfo)593   private static boolean isValidComponentInfo(ComponentInfo componentInfo) {
594     return componentInfo != null
595         && componentInfo.applicationInfo != null
596         && componentInfo.applicationInfo.packageName != null
597         && componentInfo.name != null;
598   }
599 
600   /** Behaves as {@link #queryIntentServices(Intent, int)} and currently ignores userId. */
601   @Implementation
queryIntentServicesAsUser(Intent intent, int flags, int userId)602   protected List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) {
603     return queryIntentServices(intent, flags);
604   }
605 
606   @Implementation
queryIntentActivities(Intent intent, int flags)607   protected List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
608     return this.queryIntentComponents(
609         intent,
610         flags,
611         (pkg) -> pkg.activities,
612         activityFilters,
613         (resolveInfo, activityInfo) -> resolveInfo.activityInfo = activityInfo,
614         (resolveInfo) -> resolveInfo.activityInfo,
615         ActivityInfo::new);
616   }
617 
queryIntentComponents( Intent intent, int flags, Function<PackageInfo, I[]> componentsInPackage, SortedMap<ComponentName, List<IntentFilter>> filters, BiConsumer<ResolveInfo, I> componentSetter, Function<ResolveInfo, I> componentInResolveInfo, Function<I, I> copyConstructor)618   private <I extends ComponentInfo> List<ResolveInfo> queryIntentComponents(
619       Intent intent,
620       int flags,
621       Function<PackageInfo, I[]> componentsInPackage,
622       SortedMap<ComponentName, List<IntentFilter>> filters,
623       BiConsumer<ResolveInfo, I> componentSetter,
624       Function<ResolveInfo, I> componentInResolveInfo,
625       Function<I, I> copyConstructor) {
626     synchronized (lock) {
627       if (intent.getComponent() != null) {
628         flags &= ~MATCH_DEFAULT_ONLY;
629       }
630       List<ResolveInfo> result = new ArrayList<>();
631       List<ResolveInfo> resolveInfoList = queryOverriddenIntents(intent, flags);
632       if (!resolveInfoList.isEmpty()) {
633         result.addAll(resolveInfoList);
634       }
635 
636       result.addAll(
637           queryComponentsInManifest(intent, componentsInPackage, filters, componentSetter));
638 
639       for (Iterator<ResolveInfo> iterator = result.iterator(); iterator.hasNext(); ) {
640         ResolveInfo resolveInfo = iterator.next();
641         I componentInfo = componentInResolveInfo.apply(resolveInfo);
642         if (hasSomeComponentInfo(resolveInfo) && componentInfo == null) {
643           Log.d(TAG, "ResolveInfo for different component type");
644           // different component type
645           iterator.remove();
646           continue;
647         }
648         if (componentInfo == null) {
649           // null component? Don't filter this sh...
650           continue;
651         }
652         if (!applyFlagsToResolveInfo(resolveInfo, flags)) {
653           Log.d(TAG, "ResolveInfo doesn't match flags");
654           iterator.remove();
655           continue;
656         }
657         ApplicationInfo applicationInfo = componentInfo.applicationInfo;
658         if (applicationInfo == null) {
659           String packageName = null;
660           if (getComponentForIntent(intent) != null) {
661             packageName = getComponentForIntent(intent).getPackageName();
662           } else if (intent.getPackage() != null) {
663             packageName = intent.getPackage();
664           } else if (componentInfo.packageName != null) {
665             packageName = componentInfo.packageName;
666           }
667           if (packageName != null) {
668             PackageInfo packageInfo = packageInfos.get(packageName);
669             if (packageInfo != null && packageInfo.applicationInfo != null) {
670               applicationInfo = new ApplicationInfo(packageInfo.applicationInfo);
671             } else {
672               applicationInfo = new ApplicationInfo();
673               applicationInfo.packageName = packageName;
674               applicationInfo.flags = FLAG_INSTALLED;
675             }
676           }
677         } else {
678           applicationInfo = new ApplicationInfo(applicationInfo);
679         }
680         componentInfo = copyConstructor.apply(componentInfo);
681         componentSetter.accept(resolveInfo, componentInfo);
682         componentInfo.applicationInfo = applicationInfo;
683 
684         try {
685           applyFlagsToComponentInfo(componentInfo, flags);
686         } catch (NameNotFoundException e) {
687           Log.d(TAG, "ComponentInfo doesn't match flags:" + e.getMessage());
688           iterator.remove();
689           continue;
690         }
691       }
692       Collections.sort(result, new ResolveInfoComparator());
693       return result;
694     }
695   }
696 
applyFlagsToResolveInfo(ResolveInfo resolveInfo, int flags)697   private boolean applyFlagsToResolveInfo(ResolveInfo resolveInfo, int flags) {
698     if ((flags & GET_RESOLVED_FILTER) == 0) {
699       resolveInfo.filter = null;
700     }
701     return (flags & MATCH_DEFAULT_ONLY) == 0 || resolveInfo.isDefault;
702   }
703 
queryComponentsInManifest( Intent intent, Function<PackageInfo, I[]> componentsInPackage, SortedMap<ComponentName, List<IntentFilter>> filters, BiConsumer<ResolveInfo, I> componentSetter)704   private <I extends ComponentInfo> ImmutableList<ResolveInfo> queryComponentsInManifest(
705       Intent intent,
706       Function<PackageInfo, I[]> componentsInPackage,
707       SortedMap<ComponentName, List<IntentFilter>> filters,
708       BiConsumer<ResolveInfo, I> componentSetter) {
709     synchronized (lock) {
710       if (isExplicitIntent(intent)) {
711         ComponentName component = getComponentForIntent(intent);
712         PackageInfo appPackage = packageInfos.get(component.getPackageName());
713         if (appPackage == null) {
714           return ImmutableList.of();
715         }
716         I componentInfo = findMatchingComponent(component, componentsInPackage.apply(appPackage));
717         if (componentInfo != null) {
718           List<IntentFilter> componentFilters = filters.get(component);
719           PackageInfo targetPackage = packageInfos.get(component.getPackageName());
720           if (RuntimeEnvironment.getApiLevel() >= TIRAMISU
721               && (intent.getAction() != null
722                   || intent.getCategories() != null
723                   || intent.getData() != null)
724               && componentFilters != null
725               && !component.getPackageName().equals(getContext().getPackageName())
726               && targetPackage.applicationInfo.targetSdkVersion >= TIRAMISU) {
727             // Check if the explicit intent matches filters on the target component for T+
728             boolean matchFound = false;
729             for (IntentFilter filter : componentFilters) {
730               if (matchIntentFilter(intent, filter) > 0) {
731                 matchFound = true;
732                 break;
733               }
734             }
735             if (!matchFound) {
736               Log.w(
737                   TAG,
738                   "Component "
739                       + componentInfo
740                       + " doesn't have required intent filters for "
741                       + intent);
742               return ImmutableList.of();
743             }
744           }
745           ResolveInfo resolveInfo = buildResolveInfo(componentInfo);
746           componentSetter.accept(resolveInfo, componentInfo);
747           return ImmutableList.copyOf(new ArrayList<>(Collections.singletonList(resolveInfo)));
748         }
749 
750         return ImmutableList.of();
751       } else {
752         List<ResolveInfo> resolveInfoList = new ArrayList<>();
753         Map<ComponentName, List<IntentFilter>> filtersForPackage =
754             mapForPackage(filters, intent.getPackage());
755         components:
756         for (Map.Entry<ComponentName, List<IntentFilter>> componentEntry :
757             filtersForPackage.entrySet()) {
758           ComponentName componentName = componentEntry.getKey();
759           for (IntentFilter filter : componentEntry.getValue()) {
760             int match = matchIntentFilter(intent, filter);
761             if (match > 0) {
762               PackageInfo packageInfo = packageInfos.get(componentName.getPackageName());
763               I[] componentInfoArray = componentsInPackage.apply(packageInfo);
764               if (componentInfoArray != null) {
765                 for (I componentInfo : componentInfoArray) {
766                   if (!componentInfo.name.equals(componentName.getClassName())) {
767                     continue;
768                   }
769                   ResolveInfo resolveInfo = buildResolveInfo(componentInfo, filter);
770                   resolveInfo.match = match;
771                   componentSetter.accept(resolveInfo, componentInfo);
772                   resolveInfoList.add(resolveInfo);
773                   continue components;
774                 }
775               }
776             }
777           }
778         }
779         return ImmutableList.copyOf(resolveInfoList);
780       }
781     }
782   }
783 
784   /** Behaves as {@link #queryIntentActivities(Intent, int)} and currently ignores userId. */
785   @Implementation
queryIntentActivitiesAsUser(Intent intent, int flags, int userId)786   protected List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId) {
787     return queryIntentActivities(intent, flags);
788   }
789 
790   /** Behaves as {@link #queryIntentActivities(Intent, int)} and currently ignores userId. */
791   @Implementation(minSdk = TIRAMISU)
queryIntentActivitiesAsUser( Object intent, Object flags, Object userId)792   protected List<ResolveInfo> queryIntentActivitiesAsUser(
793       /*Intent*/ Object intent, /*ResolveInfoFlags*/ Object flags, /*int*/ Object userId) {
794     return queryIntentActivities((Intent) intent, (int) ((ResolveInfoFlags) flags).getValue());
795   }
796 
797   /** Returns true if intent has specified a specific component. */
isExplicitIntent(Intent intent)798   private static boolean isExplicitIntent(Intent intent) {
799     return getComponentForIntent(intent) != null;
800   }
801 
findMatchingComponent( ComponentName componentName, T[] components)802   private static <T extends ComponentInfo> T findMatchingComponent(
803       ComponentName componentName, T[] components) {
804     if (components == null) {
805       return null;
806     }
807     for (T component : components) {
808       if (componentName.equals(new ComponentName(component.packageName, component.name))) {
809         return component;
810       }
811     }
812     return null;
813   }
814 
getComponentForIntent(Intent intent)815   private static ComponentName getComponentForIntent(Intent intent) {
816     ComponentName component = intent.getComponent();
817     if (component == null) {
818       if (intent.getSelector() != null) {
819         intent = intent.getSelector();
820         component = intent.getComponent();
821       }
822     }
823     return component;
824   }
825 
buildResolveInfo(ComponentInfo componentInfo)826   private static ResolveInfo buildResolveInfo(ComponentInfo componentInfo) {
827     ResolveInfo resolveInfo = new ResolveInfo();
828     resolveInfo.resolvePackageName = componentInfo.applicationInfo.packageName;
829     resolveInfo.labelRes = componentInfo.labelRes;
830     resolveInfo.icon = componentInfo.icon;
831     resolveInfo.nonLocalizedLabel = componentInfo.nonLocalizedLabel;
832     return resolveInfo;
833   }
834 
buildResolveInfo(ComponentInfo componentInfo, IntentFilter intentFilter)835   static ResolveInfo buildResolveInfo(ComponentInfo componentInfo, IntentFilter intentFilter) {
836     ResolveInfo info = buildResolveInfo(componentInfo);
837     info.isDefault = intentFilter.hasCategory("android.intent.category.DEFAULT");
838     info.filter = new IntentFilter(intentFilter);
839     info.priority = intentFilter.getPriority();
840     return info;
841   }
842 
843   @Implementation
checkPermission(String permName, String pkgName)844   protected int checkPermission(String permName, String pkgName) {
845     PackageInfo permissionsInfo = getInternalMutablePackageInfo(pkgName);
846     if (permissionsInfo == null || permissionsInfo.requestedPermissions == null) {
847       return PackageManager.PERMISSION_DENIED;
848     }
849 
850     String permission;
851     for (int i = 0; i < permissionsInfo.requestedPermissions.length; i++) {
852       permission = permissionsInfo.requestedPermissions[i];
853       if (permission != null && permission.equals(permName)) {
854         // The package requests this permission. Now check if it's been granted to the package.
855         if (isGrantedForBackwardsCompatibility(pkgName, permissionsInfo)) {
856           return PackageManager.PERMISSION_GRANTED;
857         }
858 
859         if ((permissionsInfo.requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED)
860             == REQUESTED_PERMISSION_GRANTED) {
861           return PackageManager.PERMISSION_GRANTED;
862         }
863       }
864     }
865 
866     return PackageManager.PERMISSION_DENIED;
867   }
868 
869   /**
870    * Returns whether a permission should be treated as granted to the package for backward
871    * compatibility reasons.
872    *
873    * <p>Before Robolectric 4.0 the ShadowPackageManager treated every requested permission as
874    * automatically granted. 4.0 changes this behavior, and only treats a permission as granted if
875    * PackageInfo.requestedPermissionFlags[permissionIndex] & REQUESTED_PERMISSION_GRANTED ==
876    * REQUESTED_PERMISSION_GRANTED which matches the real PackageManager's behavior.
877    *
878    * <p>Since many existing tests didn't set the requestedPermissionFlags on their {@code
879    * PackageInfo} objects, but assumed that all permissions are granted, we auto-grant all
880    * permissions if the requestedPermissionFlags is not set. If the requestedPermissionFlags is set,
881    * we assume that the test is configuring the permission grant state, and we don't override this
882    * setting.
883    */
isGrantedForBackwardsCompatibility(String pkgName, PackageInfo permissionsInfo)884   private boolean isGrantedForBackwardsCompatibility(String pkgName, PackageInfo permissionsInfo) {
885     // Note: it might be cleaner to auto-grant these permissions when the package is added to the
886     // PackageManager. But many existing tests modify the requested permissions _after_ adding the
887     // package to the PackageManager, without updating the requestedPermissionsFlags.
888     return permissionsInfo.requestedPermissionsFlags == null
889         // Robolectric uses the PackageParser to create the current test package's PackageInfo from
890         // the manifest XML. The parser populates the requestedPermissionsFlags, but doesn't grant
891         // the permissions. Several tests rely on the test package being granted all permissions, so
892         // we treat this as a special case.
893         || pkgName.equals(RuntimeEnvironment.getApplication().getPackageName());
894   }
895 
896   @Implementation
getReceiverInfo(ComponentName component, int flags)897   protected ActivityInfo getReceiverInfo(ComponentName component, int flags)
898       throws NameNotFoundException {
899     return getComponentInfo(
900         component,
901         flags,
902         packageInfo -> packageInfo.receivers,
903         resolveInfo -> resolveInfo.activityInfo,
904         ActivityInfo::new);
905   }
906 
907   @Implementation(minSdk = TIRAMISU)
getReceiverInfo( Object component, Object flags)908   protected ActivityInfo getReceiverInfo(
909       /*ComponentName*/ Object component, /*ComponentInfoFlags*/ Object flags)
910       throws NameNotFoundException {
911     return getReceiverInfo(
912         (ComponentName) component, (int) ((ComponentInfoFlags) flags).getValue());
913   }
914 
915   @Implementation
queryBroadcastReceivers(Intent intent, int flags)916   protected List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
917     return this.queryIntentComponents(
918         intent,
919         flags,
920         (pkg) -> pkg.receivers,
921         receiverFilters,
922         (resolveInfo, activityInfo) -> resolveInfo.activityInfo = activityInfo,
923         (resolveInfo) -> resolveInfo.activityInfo,
924         ActivityInfo::new);
925   }
926 
927   @Implementation(minSdk = TIRAMISU)
queryBroadcastReceivers( Object intent, Object flags)928   protected List<ResolveInfo> queryBroadcastReceivers(
929       /*Intent*/ Object intent, /*ResolveInfoFlags*/ Object flags) {
930     return queryBroadcastReceivers((Intent) intent, (int) ((ResolveInfoFlags) flags).getValue());
931   }
932 
matchIntentFilter(Intent intent, IntentFilter intentFilter)933   private static int matchIntentFilter(Intent intent, IntentFilter intentFilter) {
934     return intentFilter.match(
935         intent.getAction(),
936         intent.getType(),
937         intent.getScheme(),
938         intent.getData(),
939         intent.getCategories(),
940         TAG);
941   }
942 
943   @Implementation
resolveService(Intent intent, int flags)944   protected ResolveInfo resolveService(Intent intent, int flags) {
945     List<ResolveInfo> candidates = queryIntentServices(intent, flags);
946     return candidates.isEmpty() ? null : candidates.get(0);
947   }
948 
949   @Implementation
getServiceInfo(ComponentName component, int flags)950   protected ServiceInfo getServiceInfo(ComponentName component, int flags)
951       throws NameNotFoundException {
952     return getComponentInfo(
953         component,
954         flags,
955         packageInfo -> packageInfo.services,
956         resolveInfo -> resolveInfo.serviceInfo,
957         ServiceInfo::new);
958   }
959 
960   @Implementation(minSdk = TIRAMISU)
getServiceInfo( Object component, Object flags)961   protected ServiceInfo getServiceInfo(
962       /*ComponentName*/ Object component, /*ComponentInfoFlags*/ Object flags)
963       throws NameNotFoundException {
964     return getServiceInfo((ComponentName) component, (int) ((ComponentInfoFlags) flags).getValue());
965   }
966 
967   /**
968    * Modifies the component in place using.
969    *
970    * @throws NameNotFoundException when component is filtered out by a flag
971    */
applyFlagsToComponentInfo(ComponentInfo componentInfo, long flags)972   private void applyFlagsToComponentInfo(ComponentInfo componentInfo, long flags)
973       throws NameNotFoundException {
974     componentInfo.name = (componentInfo.name == null) ? "" : componentInfo.name;
975     ApplicationInfo applicationInfo = componentInfo.applicationInfo;
976     boolean isApplicationEnabled = true;
977     if (applicationInfo != null) {
978       if (applicationInfo.packageName == null) {
979         applicationInfo.packageName = componentInfo.packageName;
980       }
981       applyFlagsToApplicationInfo(componentInfo.applicationInfo, flags);
982       componentInfo.packageName = applicationInfo.packageName;
983       isApplicationEnabled = applicationInfo.enabled;
984     }
985     if ((flags & GET_META_DATA) == 0) {
986       componentInfo.metaData = null;
987     }
988     boolean isComponentEnabled = isComponentEnabled(componentInfo);
989     if ((flags & MATCH_ALL) != 0 && Build.VERSION.SDK_INT >= 23) {
990       return;
991     }
992     // Android don't override the enabled field of component with the actual value.
993     boolean isEnabledForFiltering =
994         isComponentEnabled && (Build.VERSION.SDK_INT >= 24 ? isApplicationEnabled : true);
995     if ((flags & MATCH_DISABLED_COMPONENTS) == 0 && !isEnabledForFiltering) {
996       throw new NameNotFoundException("Disabled component: " + componentInfo);
997     }
998     if (isFlagSet(flags, PackageManager.MATCH_SYSTEM_ONLY)) {
999       if (applicationInfo == null) {
1000         // TODO: for backwards compatibility just skip filtering. In future should just remove
1001         // invalid resolve infos from list
1002       } else {
1003         final int applicationFlags = applicationInfo.flags;
1004         if ((applicationFlags & ApplicationInfo.FLAG_SYSTEM) != ApplicationInfo.FLAG_SYSTEM) {
1005           throw new NameNotFoundException("Not system component: " + componentInfo);
1006         }
1007       }
1008     }
1009     if (!isFlagSet(flags, MATCH_UNINSTALLED_PACKAGES)
1010         && isValidComponentInfo(componentInfo)
1011         && hiddenPackages.contains(componentInfo.applicationInfo.packageName)) {
1012       throw new NameNotFoundException("Uninstalled package: " + componentInfo);
1013     }
1014   }
1015 
1016   @Implementation
getResourcesForApplication(@onNull ApplicationInfo applicationInfo)1017   protected Resources getResourcesForApplication(@NonNull ApplicationInfo applicationInfo)
1018       throws PackageManager.NameNotFoundException {
1019     synchronized (lock) {
1020       if (getContext().getPackageName().equals(applicationInfo.packageName)) {
1021         return getContext().getResources();
1022       } else if (packageInfos.containsKey(applicationInfo.packageName)) {
1023         Resources appResources = resources.get(applicationInfo.packageName);
1024         if (appResources == null) {
1025           appResources = new Resources(new AssetManager(), null, null);
1026           resources.put(applicationInfo.packageName, appResources);
1027         }
1028         return appResources;
1029       }
1030       Resources resources = null;
1031 
1032       try {
1033         resources =
1034             reflector(ReflectorApplicationPackageManager.class, realObject)
1035                 .getResourcesForApplication(applicationInfo);
1036       } catch (Exception ex) {
1037         // handled below
1038       }
1039       if (resources == null) {
1040         throw new NameNotFoundException(applicationInfo.packageName);
1041       }
1042       return resources;
1043     }
1044   }
1045 
1046   @Implementation
getInstalledApplications(int flags)1047   protected List<ApplicationInfo> getInstalledApplications(int flags) {
1048     return getInstalledApplications((long) flags);
1049   }
1050 
1051   @Implementation(minSdk = TIRAMISU)
getInstalledApplications(Object flags)1052   protected List<ApplicationInfo> getInstalledApplications(Object flags) {
1053     return getInstalledApplications(((PackageManager.ApplicationInfoFlags) flags).getValue());
1054   }
1055 
getInstalledApplications(long flags)1056   private List<ApplicationInfo> getInstalledApplications(long flags) {
1057     List<PackageInfo> packageInfos = getInstalledPackages(flags);
1058     List<ApplicationInfo> result = new ArrayList<>(packageInfos.size());
1059 
1060     for (PackageInfo packageInfo : packageInfos) {
1061       if (packageInfo.applicationInfo != null) {
1062         result.add(packageInfo.applicationInfo);
1063       }
1064     }
1065     return result;
1066   }
1067 
1068   @Implementation
getInstallerPackageName(String packageName)1069   protected String getInstallerPackageName(String packageName) {
1070     synchronized (lock) {
1071       // In REALISTIC mode, throw exception if the package is not installed or installed but
1072       // later uninstalled
1073       if (ConfigurationRegistry.get(GetInstallerPackageNameMode.Mode.class) == REALISTIC
1074           && (!packageInstallerMap.containsKey(packageName)
1075               || !packageInfos.containsKey(packageName))) {
1076         throw new IllegalArgumentException("Package is not installed: " + packageName);
1077       } else if (!packageInstallerMap.containsKey(packageName)) {
1078         Log.w(
1079             TAG,
1080             String.format(
1081                 "Call to getInstallerPackageName returns null for package: '%s'. Please run"
1082                     + " setInstallerPackageName to set installer package name before making the"
1083                     + " call.",
1084                 packageName));
1085       }
1086       return packageInstallerMap.get(packageName);
1087     }
1088   }
1089 
1090   @Implementation(minSdk = R)
getInstallSourceInfo(String packageName)1091   protected Object getInstallSourceInfo(String packageName) throws NameNotFoundException {
1092     if (!packageInstallSourceInfoMap.containsKey(packageName)) {
1093       throw new NameNotFoundException("Package is not installed: " + packageName);
1094     } else {
1095       return packageInstallSourceInfoMap.get(packageName);
1096     }
1097   }
1098 
1099   @Implementation
getPermissionInfo(String name, int flags)1100   protected PermissionInfo getPermissionInfo(String name, int flags) throws NameNotFoundException {
1101     PermissionInfo permissionInfo = extraPermissions.get(name);
1102     if (permissionInfo != null) {
1103       return permissionInfo;
1104     }
1105 
1106     synchronized (lock) {
1107       for (PackageInfo packageInfo : packageInfos.values()) {
1108         if (packageInfo.permissions != null) {
1109           for (PermissionInfo permission : packageInfo.permissions) {
1110             if (name.equals(permission.name)) {
1111               return createCopyPermissionInfo(permission, flags);
1112             }
1113           }
1114         }
1115       }
1116     }
1117 
1118     throw new NameNotFoundException(name);
1119   }
1120 
1121   @Implementation(minSdk = M)
shouldShowRequestPermissionRationale(String permission)1122   protected boolean shouldShowRequestPermissionRationale(String permission) {
1123     return permissionRationaleMap.containsKey(permission)
1124         ? permissionRationaleMap.get(permission)
1125         : false;
1126   }
1127 
1128   @Implementation
getSystemAvailableFeatures()1129   protected FeatureInfo[] getSystemAvailableFeatures() {
1130     return systemAvailableFeatures.isEmpty()
1131         ? null
1132         : systemAvailableFeatures.toArray(new FeatureInfo[systemAvailableFeatures.size()]);
1133   }
1134 
1135   @Implementation
verifyPendingInstall(int id, int verificationCode)1136   protected void verifyPendingInstall(int id, int verificationCode) {
1137     if (verificationResults.containsKey(id)) {
1138       throw new IllegalStateException("Multiple verifications for id=" + id);
1139     }
1140     verificationResults.put(id, verificationCode);
1141   }
1142 
1143   @Implementation
extendVerificationTimeout( int id, int verificationCodeAtTimeout, long millisecondsToDelay)1144   protected void extendVerificationTimeout(
1145       int id, int verificationCodeAtTimeout, long millisecondsToDelay) {
1146     synchronized (lock) {
1147       verificationTimeoutExtension.put(id, millisecondsToDelay);
1148       verificationCodeAtTimeoutExtension.put(id, verificationCodeAtTimeout);
1149     }
1150   }
1151 
1152   @Override
1153   @Implementation(maxSdk = LOLLIPOP_MR1)
freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer)1154   protected void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer) {}
1155 
1156   @Implementation(minSdk = M)
freeStorageAndNotify( String volumeUuid, long freeStorageSize, IPackageDataObserver observer)1157   protected void freeStorageAndNotify(
1158       String volumeUuid, long freeStorageSize, IPackageDataObserver observer) {}
1159 
1160   @Implementation
setInstallerPackageName(String targetPackage, String installerPackageName)1161   protected void setInstallerPackageName(String targetPackage, String installerPackageName) {
1162     synchronized (lock) {
1163       packageInstallerMap.put(targetPackage, installerPackageName);
1164     }
1165   }
1166 
1167   @Implementation
queryIntentContentProviders(Intent intent, int flags)1168   protected List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags) {
1169     return this.queryIntentComponents(
1170         intent,
1171         flags,
1172         (pkg) -> pkg.providers,
1173         providerFilters,
1174         (resolveInfo, providerInfo) -> resolveInfo.providerInfo = providerInfo,
1175         (resolveInfo) -> resolveInfo.providerInfo,
1176         ProviderInfo::new);
1177   }
1178 
1179   @Implementation
queryIntentContentProvidersAsUser( Intent intent, int flags, int userId)1180   protected List<ResolveInfo> queryIntentContentProvidersAsUser(
1181       Intent intent, int flags, int userId) {
1182     return Collections.emptyList();
1183   }
1184 
1185   @Implementation(minSdk = M)
getPermissionControllerPackageName()1186   protected String getPermissionControllerPackageName() {
1187     return null;
1188   }
1189 
1190   @Implementation(maxSdk = M)
getPackageSizeInfo(Object pkgName, Object uid, final Object observer)1191   protected void getPackageSizeInfo(Object pkgName, Object uid, final Object observer) {
1192     final PackageStats packageStats = packageStatsMap.get((String) pkgName);
1193     new Handler(Looper.getMainLooper())
1194         .post(
1195             () -> {
1196               try {
1197                 ((IPackageStatsObserver) observer)
1198                     .onGetStatsCompleted(packageStats, packageStats != null);
1199               } catch (RemoteException remoteException) {
1200                 remoteException.rethrowFromSystemServer();
1201               }
1202             });
1203   }
1204 
1205   @Implementation(minSdk = N)
getPackageSizeInfoAsUser(Object pkgName, Object uid, final Object observer)1206   protected void getPackageSizeInfoAsUser(Object pkgName, Object uid, final Object observer) {
1207     final PackageStats packageStats = packageStatsMap.get((String) pkgName);
1208     new Handler(Looper.getMainLooper())
1209         .post(
1210             () -> {
1211               try {
1212                 ((IPackageStatsObserver) observer)
1213                     .onGetStatsCompleted(packageStats, packageStats != null);
1214               } catch (RemoteException remoteException) {
1215                 remoteException.rethrowFromSystemServer();
1216               }
1217             });
1218   }
1219 
1220   @Override
1221   @Implementation
deletePackage(String packageName, IPackageDeleteObserver observer, int flags)1222   protected void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
1223     super.deletePackage(packageName, observer, flags);
1224   }
1225 
1226   @Implementation
currentToCanonicalPackageNames(String[] names)1227   protected String[] currentToCanonicalPackageNames(String[] names) {
1228     String[] out = new String[names.length];
1229     for (int i = 0; i < names.length; i++) {
1230       out[i] = currentToCanonicalNames.getOrDefault(names[i], names[i]);
1231     }
1232     return out;
1233   }
1234 
1235   @Implementation
canonicalToCurrentPackageNames(String[] names)1236   protected String[] canonicalToCurrentPackageNames(String[] names) {
1237     String[] out = new String[names.length];
1238     for (int i = 0; i < names.length; i++) {
1239       out[i] = canonicalToCurrentNames.getOrDefault(names[i], names[i]);
1240     }
1241     return out;
1242   }
1243 
1244   @Implementation
isSafeMode()1245   protected boolean isSafeMode() {
1246     return safeMode;
1247   }
1248 
1249   @Implementation
getApplicationIcon(String packageName)1250   protected Drawable getApplicationIcon(String packageName) throws NameNotFoundException {
1251     return applicationIcons.get(packageName);
1252   }
1253 
1254   @Implementation
getApplicationIcon(ApplicationInfo info)1255   protected Drawable getApplicationIcon(ApplicationInfo info) throws NameNotFoundException {
1256     return getApplicationIcon(info.packageName);
1257   }
1258 
1259   @Implementation
getUserBadgeForDensity(UserHandle userHandle, int i)1260   protected Drawable getUserBadgeForDensity(UserHandle userHandle, int i) {
1261     return null;
1262   }
1263 
1264   @Implementation
checkSignatures(String pkg1, String pkg2)1265   protected int checkSignatures(String pkg1, String pkg2) {
1266     try {
1267       PackageInfo packageInfo1 = getPackageInfo(pkg1, GET_SIGNING_CERTIFICATES | GET_SIGNATURES);
1268       PackageInfo packageInfo2 = getPackageInfo(pkg2, GET_SIGNING_CERTIFICATES | GET_SIGNATURES);
1269       int signaturesResult = compareSignature(packageInfo1.signatures, packageInfo2.signatures);
1270       // Use signatures field for older SDKs
1271       if (VERSION.SDK_INT < P) {
1272         return signaturesResult;
1273       } else {
1274         // Prefer signingInfo where populated, but fall back to signatures for compatibility
1275         Signature[] firstSignatures =
1276             packageInfo1.signingInfo == null
1277                     || packageInfo1.signingInfo.getApkContentsSigners() == null
1278                     || packageInfo1.signingInfo.getApkContentsSigners().length == 0
1279                 ? packageInfo1.signatures
1280                 : packageInfo1.signingInfo.getApkContentsSigners();
1281         Signature[] secondSignatures =
1282             packageInfo2.signingInfo == null
1283                     || packageInfo2.signingInfo.getApkContentsSigners() == null
1284                     || packageInfo2.signingInfo.getApkContentsSigners().length == 0
1285                 ? packageInfo2.signatures
1286                 : packageInfo2.signingInfo.getApkContentsSigners();
1287         return compareSignature(firstSignatures, secondSignatures);
1288       }
1289     } catch (NameNotFoundException e) {
1290       return SIGNATURE_UNKNOWN_PACKAGE;
1291     }
1292   }
1293 
1294   @Implementation
checkSignatures(int uid1, int uid2)1295   protected int checkSignatures(int uid1, int uid2) {
1296     return 0;
1297   }
1298 
1299   @Implementation
queryPermissionsByGroup(String group, int flags)1300   protected List<PermissionInfo> queryPermissionsByGroup(String group, int flags)
1301       throws NameNotFoundException {
1302     List<PermissionInfo> result = new ArrayList<>();
1303     for (PermissionInfo permissionInfo : extraPermissions.values()) {
1304       if (Objects.equals(permissionInfo.group, group)) {
1305         result.add(permissionInfo);
1306       }
1307     }
1308     synchronized (lock) {
1309       for (PackageInfo packageInfo : packageInfos.values()) {
1310         if (packageInfo.permissions != null) {
1311           for (PermissionInfo permission : packageInfo.permissions) {
1312             if (Objects.equals(group, permission.group)) {
1313               result.add(createCopyPermissionInfo(permission, flags));
1314             }
1315           }
1316         }
1317       }
1318     }
1319 
1320     if (result.isEmpty()) {
1321       throw new NameNotFoundException(group);
1322     }
1323 
1324     return result;
1325   }
1326 
createCopyPermissionInfo(PermissionInfo src, int flags)1327   private static PermissionInfo createCopyPermissionInfo(PermissionInfo src, int flags) {
1328     PermissionInfo matchedPermission = new PermissionInfo(src);
1329     if ((flags & GET_META_DATA) != GET_META_DATA) {
1330       matchedPermission.metaData = null;
1331     }
1332     return matchedPermission;
1333   }
1334 
getLaunchIntentForPackage(String packageName, String launcherCategory)1335   private Intent getLaunchIntentForPackage(String packageName, String launcherCategory) {
1336     Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
1337     intentToResolve.addCategory(Intent.CATEGORY_INFO);
1338     intentToResolve.setPackage(packageName);
1339     List<ResolveInfo> ris = queryIntentActivities(intentToResolve, 0);
1340 
1341     if (ris == null || ris.isEmpty()) {
1342       intentToResolve.removeCategory(Intent.CATEGORY_INFO);
1343       intentToResolve.addCategory(launcherCategory);
1344       intentToResolve.setPackage(packageName);
1345       ris = queryIntentActivities(intentToResolve, 0);
1346     }
1347     if (ris == null || ris.isEmpty()) {
1348       return null;
1349     }
1350     Intent intent = new Intent(intentToResolve);
1351     intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1352     intent.setClassName(packageName, ris.get(0).activityInfo.name);
1353     return intent;
1354   }
1355 
1356   @Implementation
getLaunchIntentForPackage(String packageName)1357   protected Intent getLaunchIntentForPackage(String packageName) {
1358     return getLaunchIntentForPackage(packageName, Intent.CATEGORY_LAUNCHER);
1359   }
1360 
1361   @Implementation
getLeanbackLaunchIntentForPackage(String packageName)1362   protected Intent getLeanbackLaunchIntentForPackage(String packageName) {
1363     return getLaunchIntentForPackage(packageName, Intent.CATEGORY_LEANBACK_LAUNCHER);
1364   }
1365 
1366   /**
1367    * In Android T, the type of {@code flags} changed from {@code int} to {@link PackageInfoFlags}
1368    */
1369   @Implementation(minSdk = N)
getPackageInfoAsUser(Object packageName, Object flagsObject, Object userId)1370   protected Object getPackageInfoAsUser(Object packageName, Object flagsObject, Object userId)
1371       throws NameNotFoundException {
1372     int flags;
1373     if (RuntimeEnvironment.getApiLevel() >= TIRAMISU) {
1374       flags = (int) ((PackageInfoFlags) flagsObject).getValue();
1375     } else {
1376       flags = (int) flagsObject;
1377     }
1378     return getPackageInfo((String) packageName, flags);
1379   }
1380 
1381   @Implementation
getPackageGids(String packageName)1382   protected int[] getPackageGids(String packageName) throws NameNotFoundException {
1383     return new int[0];
1384   }
1385 
1386   @Implementation(minSdk = N)
getPackageGids(String packageName, int flags)1387   protected int[] getPackageGids(String packageName, int flags) throws NameNotFoundException {
1388     return null;
1389   }
1390 
1391   @Implementation
getPackageUid(String packageName, int flags)1392   protected int getPackageUid(String packageName, int flags) throws NameNotFoundException {
1393     Integer uid = uidForPackage.get(packageName);
1394     if (uid == null) {
1395       throw new NameNotFoundException(packageName);
1396     }
1397     return uid;
1398   }
1399 
1400   @Implementation(minSdk = TIRAMISU)
getPackageUid(Object packageName, Object flags)1401   protected Object getPackageUid(Object packageName, Object flags) throws NameNotFoundException {
1402     return getPackageUid((String) packageName, (int) ((PackageInfoFlags) flags).getValue());
1403   }
1404 
1405   @Implementation(minSdk = N)
getPackageUidAsUser(String packageName, int userId)1406   protected int getPackageUidAsUser(String packageName, int userId) throws NameNotFoundException {
1407     return 0;
1408   }
1409 
1410   @Implementation(minSdk = N)
getPackageUidAsUser(String packageName, int flags, int userId)1411   protected int getPackageUidAsUser(String packageName, int flags, int userId)
1412       throws NameNotFoundException {
1413     return 0;
1414   }
1415 
1416   /**
1417    * @see ShadowPackageManager#addPermissionGroupInfo(android.content.pm.PermissionGroupInfo)
1418    */
1419   @Implementation
getPermissionGroupInfo(String name, int flags)1420   protected PermissionGroupInfo getPermissionGroupInfo(String name, int flags)
1421       throws NameNotFoundException {
1422     if (permissionGroups.containsKey(name)) {
1423       return new PermissionGroupInfo(permissionGroups.get(name));
1424     }
1425 
1426     throw new NameNotFoundException(name);
1427   }
1428 
1429   /**
1430    * @see ShadowPackageManager#addPermissionGroupInfo(android.content.pm.PermissionGroupInfo)
1431    */
1432   @Implementation
getAllPermissionGroups(int flags)1433   protected List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1434     ArrayList<PermissionGroupInfo> allPermissionGroups = new ArrayList<PermissionGroupInfo>();
1435 
1436     for (PermissionGroupInfo permissionGroupInfo : permissionGroups.values()) {
1437       allPermissionGroups.add(new PermissionGroupInfo(permissionGroupInfo));
1438     }
1439 
1440     return allPermissionGroups;
1441   }
1442 
1443   @Implementation
getApplicationInfo(String packageName, int flags)1444   protected ApplicationInfo getApplicationInfo(String packageName, int flags)
1445       throws NameNotFoundException {
1446     PackageInfo packageInfo = getPackageInfo(packageName, flags);
1447     if (packageInfo.applicationInfo == null) {
1448       throw new NameNotFoundException("Package found but without application info");
1449     }
1450     // Maybe query app infos from overridden resolveInfo as well?
1451     return packageInfo.applicationInfo;
1452   }
1453 
1454   @Implementation(minSdk = TIRAMISU)
getApplicationInfo(Object packageName, Object flagsObject)1455   protected ApplicationInfo getApplicationInfo(Object packageName, Object flagsObject)
1456       throws NameNotFoundException {
1457     Preconditions.checkArgument(flagsObject instanceof PackageManager.ApplicationInfoFlags);
1458     PackageManager.ApplicationInfoFlags flags = (PackageManager.ApplicationInfoFlags) flagsObject;
1459     return getApplicationInfo((String) packageName, (int) (flags).getValue());
1460   }
1461 
applyFlagsToApplicationInfo(@ullable ApplicationInfo appInfo, long flags)1462   private void applyFlagsToApplicationInfo(@Nullable ApplicationInfo appInfo, long flags)
1463       throws NameNotFoundException {
1464     if (appInfo == null) {
1465       return;
1466     }
1467     String packageName = appInfo.packageName;
1468 
1469     Integer stateOverride = applicationEnabledSettingMap.get(packageName);
1470     if (stateOverride == null) {
1471       stateOverride = COMPONENT_ENABLED_STATE_DEFAULT;
1472     }
1473     appInfo.enabled =
1474         (appInfo.enabled && stateOverride == COMPONENT_ENABLED_STATE_DEFAULT)
1475             || stateOverride == COMPONENT_ENABLED_STATE_ENABLED;
1476 
1477     synchronized (lock) {
1478       if (deletedPackages.contains(packageName)) {
1479         appInfo.flags &= ~FLAG_INSTALLED;
1480       }
1481     }
1482 
1483     if ((flags & MATCH_ALL) != 0 && Build.VERSION.SDK_INT >= 23) {
1484       return;
1485     }
1486     if ((flags & MATCH_UNINSTALLED_PACKAGES) == 0 && (appInfo.flags & FLAG_INSTALLED) == 0) {
1487       throw new NameNotFoundException("Package not installed: " + packageName);
1488     }
1489     if ((flags & MATCH_UNINSTALLED_PACKAGES) == 0 && hiddenPackages.contains(packageName)) {
1490       throw new NameNotFoundException("Package hidden: " + packageName);
1491     }
1492   }
1493 
1494   /**
1495    * Returns all the values added via {@link
1496    * ShadowPackageManager#addSystemSharedLibraryName(String)}.
1497    */
1498   @Implementation
getSystemSharedLibraryNames()1499   protected String[] getSystemSharedLibraryNames() {
1500     return systemSharedLibraryNames.toArray(new String[systemSharedLibraryNames.size()]);
1501   }
1502 
1503   @Implementation(minSdk = N)
getServicesSystemSharedLibraryPackageName()1504   protected @NonNull String getServicesSystemSharedLibraryPackageName() {
1505     return null;
1506   }
1507 
1508   @Implementation(minSdk = N)
getSharedSystemSharedLibraryPackageName()1509   protected @NonNull String getSharedSystemSharedLibraryPackageName() {
1510     return "";
1511   }
1512 
1513   @Implementation(minSdk = N)
hasSystemFeature(String name, int version)1514   protected boolean hasSystemFeature(String name, int version) {
1515     return false;
1516   }
1517 
1518   @Implementation(minSdk = M)
isPermissionRevokedByPolicy(String permName, String pkgName)1519   protected boolean isPermissionRevokedByPolicy(String permName, String pkgName) {
1520     return false;
1521   }
1522 
1523   @Implementation
addPermission(PermissionInfo info)1524   protected boolean addPermission(PermissionInfo info) {
1525     return false;
1526   }
1527 
1528   @Implementation
addPermissionAsync(PermissionInfo info)1529   protected boolean addPermissionAsync(PermissionInfo info) {
1530     return false;
1531   }
1532 
1533   @Implementation
removePermission(String name)1534   protected void removePermission(String name) {}
1535 
1536   @Implementation(minSdk = M)
grantRuntimePermission( String packageName, String permissionName, UserHandle user)1537   protected void grantRuntimePermission(
1538       String packageName, String permissionName, UserHandle user) {
1539     Integer uid;
1540     synchronized (lock) {
1541       if (!packageInfos.containsKey(packageName)) {
1542         throw new SecurityException("Package not found: " + packageName);
1543       }
1544       PackageInfo packageInfo = packageInfos.get(packageName);
1545       checkPermissionGrantStateInitialized(packageInfo);
1546 
1547       int permissionIndex = getPermissionIndex(packageInfo, permissionName);
1548       if (permissionIndex < 0) {
1549         throw new SecurityException(
1550             "Permission " + permissionName + " not requested by package " + packageName);
1551       }
1552 
1553       packageInfo.requestedPermissionsFlags[permissionIndex] |= REQUESTED_PERMISSION_GRANTED;
1554 
1555       uid = uidForPackage.get(packageName);
1556     }
1557 
1558     if (RuntimeEnvironment.getApiLevel() >= VERSION_CODES.M && uid != null) {
1559       for (Object listener : permissionListeners) {
1560         ((OnPermissionsChangedListener) listener).onPermissionsChanged(uid);
1561       }
1562     }
1563   }
1564 
1565   @Implementation(minSdk = M)
revokeRuntimePermission( String packageName, String permissionName, UserHandle user)1566   protected void revokeRuntimePermission(
1567       String packageName, String permissionName, UserHandle user) {
1568     Integer uid;
1569     synchronized (lock) {
1570       if (!packageInfos.containsKey(packageName)) {
1571         throw new SecurityException("Package not found: " + packageName);
1572       }
1573       PackageInfo packageInfo = packageInfos.get(packageName);
1574       checkPermissionGrantStateInitialized(packageInfo);
1575 
1576       int permissionIndex = getPermissionIndex(packageInfo, permissionName);
1577       if (permissionIndex < 0) {
1578         throw new SecurityException(
1579             "Permission " + permissionName + " not requested by package " + packageName);
1580       }
1581 
1582       packageInfo.requestedPermissionsFlags[permissionIndex] &= ~REQUESTED_PERMISSION_GRANTED;
1583 
1584       uid = uidForPackage.get(packageName);
1585     }
1586 
1587     if (RuntimeEnvironment.getApiLevel() >= VERSION_CODES.M && uid != null) {
1588       for (Object listener : permissionListeners) {
1589         ((OnPermissionsChangedListener) listener).onPermissionsChanged(uid);
1590       }
1591     }
1592   }
1593 
checkPermissionGrantStateInitialized(PackageInfo packageInfo)1594   private void checkPermissionGrantStateInitialized(PackageInfo packageInfo) {
1595     if (packageInfo.requestedPermissionsFlags == null) {
1596       // In the real OS this would never be null, but tests don't necessarily initialize this
1597       // structure.
1598       throw new SecurityException(
1599           "Permission grant state (PackageInfo.requestedPermissionFlags) "
1600               + "is null. This operation requires this variable to be initialized.");
1601     }
1602   }
1603 
1604   /**
1605    * Returns the index of the given permission in the PackageInfo.requestedPermissions array, or -1
1606    * if it's not found.
1607    */
getPermissionIndex(PackageInfo packageInfo, String permissionName)1608   private int getPermissionIndex(PackageInfo packageInfo, String permissionName) {
1609     if (packageInfo.requestedPermissions != null) {
1610       for (int i = 0; i < packageInfo.requestedPermissions.length; i++) {
1611         if (permissionName.equals(packageInfo.requestedPermissions[i])) {
1612           return i;
1613         }
1614       }
1615     }
1616 
1617     return -1;
1618   }
1619 
1620   /**
1621    * This method differs from the real implementation in that we only return the permission flags
1622    * that were added via updatePermissionFlags, and do not perform any verification of permissions,
1623    * packages or users.
1624    */
1625   @Implementation(minSdk = M)
getPermissionFlags(String permissionName, String packageName, UserHandle user)1626   protected int getPermissionFlags(String permissionName, String packageName, UserHandle user) {
1627     if (permissionFlags.containsKey(packageName)) {
1628       return permissionFlags.get(packageName).getOrDefault(permissionName, /* defaultValue= */ 0);
1629     }
1630 
1631     return 0;
1632   }
1633 
1634   /**
1635    * This method differs from the real implementation in that no permission checking or package
1636    * existent checks are performed here.
1637    */
1638   @Implementation(minSdk = M)
updatePermissionFlags( String permissionName, String packageName, @PackageManager.PermissionFlags int flagMask, @PackageManager.PermissionFlags int flagValues, UserHandle user)1639   protected void updatePermissionFlags(
1640       String permissionName,
1641       String packageName,
1642       @PackageManager.PermissionFlags int flagMask,
1643       @PackageManager.PermissionFlags int flagValues,
1644       UserHandle user) {
1645     if (!permissionFlags.containsKey(packageName)) {
1646       permissionFlags.put(packageName, new HashMap<String, Integer>());
1647     }
1648 
1649     int existingFlags =
1650         permissionFlags.get(packageName).getOrDefault(permissionName, /* defaultValue= */ 0);
1651     int flagsToKeep = ~flagMask & existingFlags;
1652     int flagsToChange = flagMask & flagValues;
1653     int newFlags = flagsToKeep | flagsToChange;
1654 
1655     permissionFlags.get(packageName).put(permissionName, newFlags);
1656   }
1657 
1658   @Implementation
getUidForSharedUser(String sharedUserName)1659   protected int getUidForSharedUser(String sharedUserName) throws NameNotFoundException {
1660     return 0;
1661   }
1662 
1663   @Implementation(minSdk = N)
getInstalledPackagesAsUser(int flags, int userId)1664   protected List<PackageInfo> getInstalledPackagesAsUser(int flags, int userId) {
1665     return null;
1666   }
1667 
1668   @Implementation
getPackagesHoldingPermissions(String[] permissions, int flags)1669   protected List<PackageInfo> getPackagesHoldingPermissions(String[] permissions, int flags) {
1670     synchronized (lock) {
1671       List<PackageInfo> packageInfosWithPermissions = new ArrayList<>();
1672       for (PackageInfo packageInfo : packageInfos.values()) {
1673         for (String permission : permissions) {
1674           int permissionIndex = getPermissionIndex(packageInfo, permission);
1675           if (permissionIndex >= 0) {
1676             packageInfosWithPermissions.add(packageInfo);
1677             break;
1678           }
1679         }
1680       }
1681       return packageInfosWithPermissions;
1682     }
1683   }
1684 
1685   @Implementation(minSdk = S)
getGroupOfPlatformPermission( String permissionName, Executor executor, Consumer<String> callback)1686   public void getGroupOfPlatformPermission(
1687       String permissionName, Executor executor, Consumer<String> callback) {
1688     String permissionGroup = null;
1689     try {
1690       PermissionInfo permissionInfo =
1691           getPermissionInfo(permissionName, PackageManager.GET_META_DATA);
1692       permissionGroup = permissionInfo.group;
1693     } catch (NameNotFoundException ignored) {
1694       // fall through
1695     }
1696     final String finalPermissionGroup = permissionGroup;
1697     executor.execute(() -> callback.accept(finalPermissionGroup));
1698   }
1699 
1700   /** Behaves as {@link #resolveActivity(Intent, int)} and currently ignores userId. */
1701   @Implementation
resolveActivityAsUser(Intent intent, int flags, int userId)1702   protected ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) {
1703     return resolveActivity(intent, flags);
1704   }
1705 
1706   @Implementation(minSdk = TIRAMISU)
resolveActivityAsUser(Object intent, Object flags, Object userId)1707   protected ResolveInfo resolveActivityAsUser(Object intent, Object flags, Object userId) {
1708     return resolveActivity((Intent) intent, (int) ((ResolveInfoFlags) flags).getValue());
1709   }
1710 
1711   @Implementation(minSdk = TIRAMISU)
resolveServiceAsUser(Object intent, Object flags, Object userId)1712   protected ResolveInfo resolveServiceAsUser(Object intent, Object flags, Object userId) {
1713     return resolveService((Intent) intent, (int) ((ResolveInfoFlags) flags).getValue());
1714   }
1715 
1716   @Implementation
queryIntentActivityOptions( ComponentName caller, Intent[] specifics, Intent intent, int flags)1717   protected List<ResolveInfo> queryIntentActivityOptions(
1718       ComponentName caller, Intent[] specifics, Intent intent, int flags) {
1719     return null;
1720   }
1721 
1722   @Implementation(minSdk = N)
queryBroadcastReceiversAsUser(Intent intent, int flags, int userId)1723   protected List<ResolveInfo> queryBroadcastReceiversAsUser(Intent intent, int flags, int userId) {
1724     return null;
1725   }
1726 
1727   @Implementation
queryContentProviders(String processName, int uid, int flags)1728   protected List<ProviderInfo> queryContentProviders(String processName, int uid, int flags) {
1729     return null;
1730   }
1731 
1732   @Implementation
getInstrumentationInfo(ComponentName className, int flags)1733   protected InstrumentationInfo getInstrumentationInfo(ComponentName className, int flags)
1734       throws NameNotFoundException {
1735     return null;
1736   }
1737 
1738   @Implementation
queryInstrumentation(String targetPackage, int flags)1739   protected List<InstrumentationInfo> queryInstrumentation(String targetPackage, int flags) {
1740     return null;
1741   }
1742 
1743   @Nullable
1744   @Implementation
getDrawable( String packageName, @DrawableRes int resId, @Nullable ApplicationInfo appInfo)1745   protected Drawable getDrawable(
1746       String packageName, @DrawableRes int resId, @Nullable ApplicationInfo appInfo) {
1747     Drawable result = drawables.get(new Pair<>(packageName, resId));
1748     if (result != null) {
1749       return result;
1750     }
1751     return reflector(ReflectorApplicationPackageManager.class, realObject)
1752         .getDrawable(packageName, resId, appInfo);
1753   }
1754 
1755   /**
1756    * Returns a user stored String resource with {@code resId} corresponding to {@code packageName}.
1757    * User can store this String via {@link #addStringResource(String, int, String)}.
1758    *
1759    * <p>Real method is called if the user has not stored a String corresponding to {@code resId} and
1760    * {@code packageName}.
1761    */
1762   @Nullable
1763   @Implementation
getText(String packageName, int resId, ApplicationInfo appInfo)1764   protected CharSequence getText(String packageName, int resId, ApplicationInfo appInfo) {
1765     if (stringResources.containsKey(packageName)
1766         && stringResources.get(packageName).containsKey(resId)) {
1767       return stringResources.get(packageName).get(resId);
1768     }
1769     return reflector(ReflectorApplicationPackageManager.class, realObject)
1770         .getText(packageName, resId, appInfo);
1771   }
1772 
1773   @Implementation
getActivityIcon(ComponentName activityName)1774   protected Drawable getActivityIcon(ComponentName activityName) throws NameNotFoundException {
1775     Drawable result = drawableList.get(activityName);
1776     if (result != null) {
1777       return result;
1778     }
1779     return reflector(ReflectorApplicationPackageManager.class, realObject)
1780         .getActivityIcon(activityName);
1781   }
1782 
1783   @Implementation
getDefaultActivityIcon()1784   protected Drawable getDefaultActivityIcon() {
1785     return Resources.getSystem().getDrawable(com.android.internal.R.drawable.sym_def_app_icon);
1786   }
1787 
1788   @Implementation
getResourcesForActivity(ComponentName activityName)1789   protected Resources getResourcesForActivity(ComponentName activityName)
1790       throws NameNotFoundException {
1791     return getResourcesForApplication(activityName.getPackageName());
1792   }
1793 
1794   @Implementation
getResourcesForApplication(String appPackageName)1795   protected Resources getResourcesForApplication(String appPackageName)
1796       throws NameNotFoundException {
1797     synchronized (lock) {
1798       if (getContext().getPackageName().equals(appPackageName)) {
1799         return getContext().getResources();
1800       } else if (packageInfos.containsKey(appPackageName)) {
1801         Resources appResources = resources.get(appPackageName);
1802         if (appResources == null) {
1803           appResources = new Resources(new AssetManager(), null, null);
1804           resources.put(appPackageName, appResources);
1805         }
1806         return appResources;
1807       }
1808       throw new NameNotFoundException(appPackageName);
1809     }
1810   }
1811 
1812   @Implementation
getResourcesForApplicationAsUser(String appPackageName, int userId)1813   protected Resources getResourcesForApplicationAsUser(String appPackageName, int userId)
1814       throws NameNotFoundException {
1815     return null;
1816   }
1817 
1818   @Implementation(minSdk = M)
addOnPermissionsChangeListener(Object listener)1819   protected void addOnPermissionsChangeListener(Object listener) {
1820     permissionListeners.add(listener);
1821   }
1822 
1823   @Implementation(minSdk = M)
removeOnPermissionsChangeListener(Object listener)1824   protected void removeOnPermissionsChangeListener(Object listener) {
1825     permissionListeners.remove(listener);
1826   }
1827 
1828   @Implementation(maxSdk = O_MR1)
installPackage( Object packageURI, Object observer, Object flags, Object installerPackageName)1829   protected void installPackage(
1830       Object packageURI, Object observer, Object flags, Object installerPackageName) {}
1831 
1832   @Implementation
installExistingPackage(String packageName)1833   protected int installExistingPackage(String packageName) throws NameNotFoundException {
1834     return 0;
1835   }
1836 
1837   @Implementation(minSdk = N)
installExistingPackageAsUser(String packageName, int userId)1838   protected int installExistingPackageAsUser(String packageName, int userId)
1839       throws NameNotFoundException {
1840     return 0;
1841   }
1842 
1843   @Implementation(minSdk = M)
verifyIntentFilter(int id, int verificationCode, List<String> failedDomains)1844   protected void verifyIntentFilter(int id, int verificationCode, List<String> failedDomains) {}
1845 
1846   @Implementation(minSdk = N)
getIntentVerificationStatusAsUser(String packageName, int userId)1847   protected int getIntentVerificationStatusAsUser(String packageName, int userId) {
1848     return 0;
1849   }
1850 
1851   @Implementation(minSdk = N)
updateIntentVerificationStatusAsUser( String packageName, int status, int userId)1852   protected boolean updateIntentVerificationStatusAsUser(
1853       String packageName, int status, int userId) {
1854     return false;
1855   }
1856 
1857   @Implementation(minSdk = M)
getIntentFilterVerifications(String packageName)1858   protected List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName) {
1859     return null;
1860   }
1861 
1862   @Implementation(minSdk = M)
getAllIntentFilters(String packageName)1863   protected List<IntentFilter> getAllIntentFilters(String packageName) {
1864     return null;
1865   }
1866 
1867   @Implementation(minSdk = N)
getDefaultBrowserPackageNameAsUser(int userId)1868   protected String getDefaultBrowserPackageNameAsUser(int userId) {
1869     return defaultBrowsers.get(userId);
1870   }
1871 
1872   @Implementation(minSdk = N)
setDefaultBrowserPackageNameAsUser(String packageName, int userId)1873   protected boolean setDefaultBrowserPackageNameAsUser(String packageName, int userId) {
1874     defaultBrowsers.put(userId, packageName);
1875     return true;
1876   }
1877 
1878   @Implementation(minSdk = M)
getMoveStatus(int moveId)1879   protected int getMoveStatus(int moveId) {
1880     return 0;
1881   }
1882 
1883   @Implementation(minSdk = M)
registerMoveCallback(Object callback, Object handler)1884   protected void registerMoveCallback(Object callback, Object handler) {}
1885 
1886   @Implementation(minSdk = M)
unregisterMoveCallback(Object callback)1887   protected void unregisterMoveCallback(Object callback) {}
1888 
1889   @Implementation(minSdk = M)
movePackage(Object packageName, Object vol)1890   protected Object movePackage(Object packageName, Object vol) {
1891     return 0;
1892   }
1893 
1894   @Implementation(minSdk = M)
getPackageCurrentVolume(Object app)1895   protected Object getPackageCurrentVolume(Object app) {
1896     return null;
1897   }
1898 
1899   @Implementation(minSdk = M)
getPackageCandidateVolumes(ApplicationInfo app)1900   protected List<VolumeInfo> getPackageCandidateVolumes(ApplicationInfo app) {
1901     return null;
1902   }
1903 
1904   @Implementation(minSdk = M)
movePrimaryStorage(Object vol)1905   protected Object movePrimaryStorage(Object vol) {
1906     return 0;
1907   }
1908 
1909   @Implementation(minSdk = M)
getPrimaryStorageCurrentVolume()1910   protected @Nullable Object getPrimaryStorageCurrentVolume() {
1911     return null;
1912   }
1913 
1914   @Implementation(minSdk = M)
getPrimaryStorageCandidateVolumes()1915   protected @NonNull List<VolumeInfo> getPrimaryStorageCandidateVolumes() {
1916     return null;
1917   }
1918 
1919   @Implementation(minSdk = N)
deletePackageAsUser( String packageName, IPackageDeleteObserver observer, int flags, int userId)1920   protected void deletePackageAsUser(
1921       String packageName, IPackageDeleteObserver observer, int flags, int userId) {}
1922 
1923   @Implementation
clearApplicationUserData(String packageName, IPackageDataObserver observer)1924   protected void clearApplicationUserData(String packageName, IPackageDataObserver observer) {
1925     clearedApplicationUserDataPackages.add(packageName);
1926   }
1927 
1928   @Implementation
deleteApplicationCacheFiles(String packageName, IPackageDataObserver observer)1929   protected void deleteApplicationCacheFiles(String packageName, IPackageDataObserver observer) {}
1930 
1931   @Implementation(minSdk = N)
deleteApplicationCacheFilesAsUser( String packageName, int userId, IPackageDataObserver observer)1932   protected void deleteApplicationCacheFilesAsUser(
1933       String packageName, int userId, IPackageDataObserver observer) {}
1934 
1935   @Implementation(minSdk = M)
freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi)1936   protected void freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi) {}
1937 
1938   @Implementation(minSdk = N, maxSdk = O_MR1)
setPackagesSuspendedAsUser( String[] packageNames, boolean suspended, int userId)1939   protected String[] setPackagesSuspendedAsUser(
1940       String[] packageNames, boolean suspended, int userId) {
1941     return null;
1942   }
1943 
1944   @Implementation(minSdk = N)
isPackageSuspendedForUser(String packageName, int userId)1945   protected boolean isPackageSuspendedForUser(String packageName, int userId) {
1946     return false;
1947   }
1948 
1949   @Implementation
addPackageToPreferred(String packageName)1950   protected void addPackageToPreferred(String packageName) {}
1951 
1952   @Implementation
removePackageFromPreferred(String packageName)1953   protected void removePackageFromPreferred(String packageName) {}
1954 
1955   @Implementation
getPreferredPackages(int flags)1956   protected List<PackageInfo> getPreferredPackages(int flags) {
1957     return null;
1958   }
1959 
1960   @Implementation
addPreferredActivity( IntentFilter filter, int match, ComponentName[] set, ComponentName activity)1961   public void addPreferredActivity(
1962       IntentFilter filter, int match, ComponentName[] set, ComponentName activity) {
1963     addPreferredActivityInternal(filter, activity, preferredActivities);
1964   }
1965 
1966   @Implementation
replacePreferredActivity( IntentFilter filter, int match, ComponentName[] set, ComponentName activity)1967   protected void replacePreferredActivity(
1968       IntentFilter filter, int match, ComponentName[] set, ComponentName activity) {
1969     addPreferredActivity(filter, match, set, activity);
1970   }
1971 
1972   @Implementation
getPreferredActivities( List<IntentFilter> outFilters, List<ComponentName> outActivities, String packageName)1973   public int getPreferredActivities(
1974       List<IntentFilter> outFilters, List<ComponentName> outActivities, String packageName) {
1975     return getPreferredActivitiesInternal(
1976         outFilters, outActivities, packageName, preferredActivities);
1977   }
1978 
1979   @Implementation
clearPackagePreferredActivities(String packageName)1980   protected void clearPackagePreferredActivities(String packageName) {
1981     clearPackagePreferredActivitiesInternal(packageName, preferredActivities);
1982   }
1983 
1984   @Implementation
getHomeActivities(List<ResolveInfo> outActivities)1985   protected ComponentName getHomeActivities(List<ResolveInfo> outActivities) {
1986     return null;
1987   }
1988 
1989   @Implementation(minSdk = N)
flushPackageRestrictionsAsUser(int userId)1990   protected void flushPackageRestrictionsAsUser(int userId) {}
1991 
1992   @Implementation
setApplicationHiddenSettingAsUser( String packageName, boolean hidden, UserHandle user)1993   protected boolean setApplicationHiddenSettingAsUser(
1994       String packageName, boolean hidden, UserHandle user) {
1995     synchronized (lock) {
1996       // Note that this ignores the UserHandle parameter
1997       if (!packageInfos.containsKey(packageName)) {
1998         // Package doesn't exist
1999         return false;
2000       }
2001       if (hidden) {
2002         hiddenPackages.add(packageName);
2003       } else {
2004         hiddenPackages.remove(packageName);
2005       }
2006 
2007       return true;
2008     }
2009   }
2010 
2011   @Implementation
getApplicationHiddenSettingAsUser(String packageName, UserHandle user)2012   protected boolean getApplicationHiddenSettingAsUser(String packageName, UserHandle user) {
2013     // Note that this ignores the UserHandle parameter
2014     synchronized (lock) {
2015       if (!packageInfos.containsKey(packageName)) {
2016         // Match Android behaviour of returning true if package isn't found
2017         return true;
2018       }
2019       return hiddenPackages.contains(packageName);
2020     }
2021   }
2022 
2023   @Implementation
getVerifierDeviceIdentity()2024   protected VerifierDeviceIdentity getVerifierDeviceIdentity() {
2025     return null;
2026   }
2027 
2028   @Implementation(minSdk = LOLLIPOP_MR1)
isUpgrade()2029   protected boolean isUpgrade() {
2030     return false;
2031   }
2032 
2033   @Implementation
isPackageAvailable(String packageName)2034   protected boolean isPackageAvailable(String packageName) {
2035     return false;
2036   }
2037 
2038   @Implementation
addCrossProfileIntentFilter( IntentFilter filter, int sourceUserId, int targetUserId, int flags)2039   protected void addCrossProfileIntentFilter(
2040       IntentFilter filter, int sourceUserId, int targetUserId, int flags) {}
2041 
2042   @Implementation
clearCrossProfileIntentFilters(int sourceUserId)2043   protected void clearCrossProfileIntentFilters(int sourceUserId) {}
2044 
2045   /**
2046    * Gets the unbadged icon based on the values set by {@link
2047    * ShadowPackageManager#setUnbadgedApplicationIcon} or returns null if nothing has been set.
2048    */
2049   @Implementation(minSdk = LOLLIPOP_MR1)
loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo)2050   protected Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) {
2051     Drawable result = unbadgedApplicationIcons.get(itemInfo.packageName);
2052     if (result != null) {
2053       return result;
2054     }
2055     return reflector(ReflectorApplicationPackageManager.class, realObject)
2056         .loadUnbadgedItemIcon(itemInfo, appInfo);
2057   }
2058 
2059   /**
2060    * Adds a profile badge to the icon.
2061    *
2062    * <p>This implementation just returns the unbadged icon, as some default implementations add an
2063    * internal resource to the icon that is unavailable to Robolectric.
2064    */
2065   @Implementation
getUserBadgedIcon(Drawable icon, UserHandle user)2066   protected Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
2067     return icon;
2068   }
2069 
2070   @Implementation(minSdk = O)
canRequestPackageInstalls()2071   protected boolean canRequestPackageInstalls() {
2072     return canRequestPackageInstalls;
2073   }
2074 
2075   @Implementation(minSdk = O)
getChangedPackages(int sequenceNumber)2076   protected Object getChangedPackages(int sequenceNumber) {
2077     if (sequenceNumber < 0 || sequenceNumberChangedPackagesMap.get(sequenceNumber).isEmpty()) {
2078       return null;
2079     }
2080     return new ChangedPackages(
2081         sequenceNumber + 1, new ArrayList<>(sequenceNumberChangedPackagesMap.get(sequenceNumber)));
2082   }
2083 
2084   @Implementation(minSdk = P)
getSystemTextClassifierPackageName()2085   public String getSystemTextClassifierPackageName() {
2086     return "";
2087   }
2088 
2089   @Implementation(minSdk = P)
2090   @HiddenApi
setPackagesSuspended( String[] packageNames, boolean suspended, PersistableBundle appExtras, PersistableBundle launcherExtras, String dialogMessage)2091   protected String[] setPackagesSuspended(
2092       String[] packageNames,
2093       boolean suspended,
2094       PersistableBundle appExtras,
2095       PersistableBundle launcherExtras,
2096       String dialogMessage) {
2097     return setPackagesSuspended(
2098         packageNames, suspended, appExtras, launcherExtras, dialogMessage, /* dialogInfo= */ null);
2099   }
2100 
2101   @Implementation(minSdk = Q)
2102   @HiddenApi
setPackagesSuspended( Object packageNames, Object suspended, Object appExtras, Object launcherExtras, Object dialogInfo)2103   protected /* String[] */ Object setPackagesSuspended(
2104       /* String[] */ Object packageNames,
2105       /* boolean */ Object suspended,
2106       /* PersistableBundle */ Object appExtras,
2107       /* PersistableBundle */ Object launcherExtras,
2108       /* SuspendDialogInfo */ Object dialogInfo) {
2109     return setPackagesSuspended(
2110         (String[]) packageNames,
2111         (boolean) suspended,
2112         (PersistableBundle) appExtras,
2113         (PersistableBundle) launcherExtras,
2114         /* dialogMessage= */ null,
2115         dialogInfo);
2116   }
2117 
2118   @Implementation(minSdk = R)
isAutoRevokeWhitelisted()2119   protected boolean isAutoRevokeWhitelisted() {
2120     return whitelisted;
2121   }
2122 
2123   /**
2124    * Sets {@code packageNames} suspension status to {@code suspended} in the package manager.
2125    *
2126    * <p>At least one of {@code dialogMessage} and {@code dialogInfo} should be null.
2127    */
setPackagesSuspended( String[] packageNames, boolean suspended, PersistableBundle appExtras, PersistableBundle launcherExtras, String dialogMessage, Object dialogInfo)2128   private String[] setPackagesSuspended(
2129       String[] packageNames,
2130       boolean suspended,
2131       PersistableBundle appExtras,
2132       PersistableBundle launcherExtras,
2133       String dialogMessage,
2134       Object dialogInfo) {
2135     if (hasProfileOwnerOrDeviceOwnerOnCurrentUser()
2136         && (VERSION.SDK_INT < VERSION_CODES.Q
2137             || !isCurrentApplicationProfileOwnerOrDeviceOwner())) {
2138       throw new UnsupportedOperationException();
2139     }
2140     ArrayList<String> unupdatedPackages = new ArrayList<>();
2141     for (String packageName : packageNames) {
2142       if (!canSuspendPackage(packageName)) {
2143         unupdatedPackages.add(packageName);
2144         continue;
2145       }
2146       PackageSetting setting = packageSettings.get(packageName);
2147       if (setting == null) {
2148         unupdatedPackages.add(packageName);
2149         continue;
2150       }
2151       setting.setSuspended(suspended, dialogMessage, dialogInfo, appExtras, launcherExtras);
2152     }
2153     return unupdatedPackages.toArray(new String[0]);
2154   }
2155 
2156   /** Returns whether the current user profile has a profile owner or a device owner. */
isCurrentApplicationProfileOwnerOrDeviceOwner()2157   private boolean isCurrentApplicationProfileOwnerOrDeviceOwner() {
2158     String currentApplication = getContext().getPackageName();
2159     DevicePolicyManager devicePolicyManager =
2160         (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
2161     return devicePolicyManager.isProfileOwnerApp(currentApplication)
2162         || devicePolicyManager.isDeviceOwnerApp(currentApplication);
2163   }
2164 
2165   /** Returns whether the current user profile has a profile owner or a device owner. */
hasProfileOwnerOrDeviceOwnerOnCurrentUser()2166   private boolean hasProfileOwnerOrDeviceOwnerOnCurrentUser() {
2167     DevicePolicyManager devicePolicyManager =
2168         (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
2169     return devicePolicyManager.getProfileOwner() != null
2170         || (UserHandle.of(UserHandle.myUserId()).isSystem()
2171             && devicePolicyManager.getDeviceOwner() != null);
2172   }
2173 
canSuspendPackage(String packageName)2174   private boolean canSuspendPackage(String packageName) {
2175     // This code approximately mirrors PackageManagerService#canSuspendPackageForUserLocked.
2176     return !packageName.equals(getContext().getPackageName())
2177         && !isPackageDeviceAdmin(packageName)
2178         && !isPackageActiveLauncher(packageName)
2179         && !isPackageRequiredInstaller(packageName)
2180         && !isPackageRequiredUninstaller(packageName)
2181         && !isPackageRequiredVerifier(packageName)
2182         && !isPackageDefaultDialer(packageName)
2183         && !packageName.equals(PLATFORM_PACKAGE_NAME);
2184   }
2185 
isPackageDeviceAdmin(String packageName)2186   private boolean isPackageDeviceAdmin(String packageName) {
2187     DevicePolicyManager devicePolicyManager =
2188         (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
2189     // Strictly speaking, this should be devicePolicyManager.getDeviceOwnerComponentOnAnyUser(),
2190     // but that method is currently not shadowed.
2191     return packageName.equals(devicePolicyManager.getDeviceOwner());
2192   }
2193 
isPackageActiveLauncher(String packageName)2194   private boolean isPackageActiveLauncher(String packageName) {
2195     Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME);
2196     ResolveInfo info = resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
2197     return info != null && packageName.equals(info.activityInfo.packageName);
2198   }
2199 
isPackageRequiredInstaller(String packageName)2200   private boolean isPackageRequiredInstaller(String packageName) {
2201     Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
2202     intent.addCategory(Intent.CATEGORY_DEFAULT);
2203     intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
2204     ResolveInfo info =
2205         resolveActivity(
2206             intent,
2207             PackageManager.MATCH_SYSTEM_ONLY
2208                 | PackageManager.MATCH_DIRECT_BOOT_AWARE
2209                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
2210     return info != null && packageName.equals(info.activityInfo.packageName);
2211   }
2212 
isPackageRequiredUninstaller(String packageName)2213   private boolean isPackageRequiredUninstaller(String packageName) {
2214     final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
2215     intent.addCategory(Intent.CATEGORY_DEFAULT);
2216     intent.setData(Uri.fromParts(PACKAGE_SCHEME, "foo.bar", null));
2217     ResolveInfo info =
2218         resolveActivity(
2219             intent,
2220             PackageManager.MATCH_SYSTEM_ONLY
2221                 | PackageManager.MATCH_DIRECT_BOOT_AWARE
2222                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
2223     return info != null && packageName.equals(info.activityInfo.packageName);
2224   }
2225 
isPackageRequiredVerifier(String packageName)2226   private boolean isPackageRequiredVerifier(String packageName) {
2227     final Intent intent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
2228     List<ResolveInfo> infos =
2229         queryBroadcastReceivers(
2230             intent,
2231             PackageManager.MATCH_SYSTEM_ONLY
2232                 | PackageManager.MATCH_DIRECT_BOOT_AWARE
2233                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
2234     if (infos != null) {
2235       for (ResolveInfo info : infos) {
2236         if (packageName.equals(info.activityInfo.packageName)) {
2237           return true;
2238         }
2239       }
2240     }
2241     return false;
2242   }
2243 
isPackageDefaultDialer(String packageName)2244   private boolean isPackageDefaultDialer(String packageName) {
2245     TelecomManager telecomManager =
2246         (TelecomManager) getContext().getSystemService(Context.TELECOM_SERVICE);
2247     return packageName.equals(telecomManager.getDefaultDialerPackage());
2248   }
2249 
2250   @HiddenApi
2251   @Implementation(minSdk = Q)
2252   @RequiresPermission(permission.SUSPEND_APPS)
getUnsuspendablePackages(String[] packageNames)2253   protected String[] getUnsuspendablePackages(String[] packageNames) {
2254     checkNotNull(packageNames, "packageNames cannot be null");
2255     if (getContext().checkSelfPermission(permission.SUSPEND_APPS)
2256         != PackageManager.PERMISSION_GRANTED) {
2257       throw new SecurityException("Current process does not have " + permission.SUSPEND_APPS);
2258     }
2259     ArrayList<String> unsuspendablePackages = new ArrayList<>();
2260     for (String packageName : packageNames) {
2261       if (!canSuspendPackage(packageName)) {
2262         unsuspendablePackages.add(packageName);
2263       }
2264     }
2265     return unsuspendablePackages.toArray(new String[0]);
2266   }
2267 
2268   @HiddenApi
2269   @Implementation(minSdk = P)
isPackageSuspended(String packageName)2270   protected boolean isPackageSuspended(String packageName) throws NameNotFoundException {
2271     PackageSetting setting = packageSettings.get(packageName);
2272     if (setting == null) {
2273       throw new NameNotFoundException(packageName);
2274     }
2275     return setting.isSuspended();
2276   }
2277 
2278   @Implementation(minSdk = O)
isInstantApp(String packageName)2279   protected boolean isInstantApp(String packageName) {
2280     synchronized (lock) {
2281       PackageInfo pi = packageInfos.get(packageName);
2282       if (pi == null) {
2283         return false;
2284       }
2285       ApplicationInfo ai = pi.applicationInfo;
2286       if (ai == null) {
2287         return false;
2288       }
2289       return ai.isInstantApp();
2290     }
2291   }
2292 
2293   @HiddenApi
2294   @Implementation(minSdk = Q)
setDistractingPackageRestrictions(String[] packages, int restrictionFlags)2295   protected String[] setDistractingPackageRestrictions(String[] packages, int restrictionFlags) {
2296     for (String pkg : packages) {
2297       distractingPackageRestrictions.put(pkg, restrictionFlags);
2298     }
2299     return new String[0];
2300   }
2301 
getContext()2302   private Context getContext() {
2303     return reflector(ReflectorApplicationPackageManager.class, realObject).getContext();
2304   }
2305 
2306   /** Stub that will always throw. */
2307   @Implementation(minSdk = S)
getProperty( String propertyName, String packageName)2308   protected Object /* PackageManager.Property */ getProperty(
2309       String propertyName, String packageName) throws NameNotFoundException {
2310     // TODO: in future read this value from parsed manifest
2311     throw new NameNotFoundException("unsupported");
2312   }
2313 
2314   /** Stub that will always throw. */
2315   @Implementation(minSdk = S)
getProperty( String propertyName, ComponentName name)2316   protected Object /* PackageManager.Property */ getProperty(
2317       String propertyName, ComponentName name) throws NameNotFoundException {
2318     // TODO: in future read this value from parsed manifest
2319     throw new NameNotFoundException("unsupported");
2320   }
2321 
2322   /** Reflector interface for {@link ApplicationPackageManager}'s internals. */
2323   @ForType(ApplicationPackageManager.class)
2324   private interface ReflectorApplicationPackageManager {
2325 
2326     @Direct
getResourcesForApplication(@onNull ApplicationInfo applicationInfo)2327     Resources getResourcesForApplication(@NonNull ApplicationInfo applicationInfo);
2328 
2329     @Direct
getDrawable( String packageName, @DrawableRes int resId, @Nullable ApplicationInfo appInfo)2330     Drawable getDrawable(
2331         String packageName, @DrawableRes int resId, @Nullable ApplicationInfo appInfo);
2332 
2333     @Direct
getText(String packageName, @StringRes int resId, ApplicationInfo appInfo)2334     CharSequence getText(String packageName, @StringRes int resId, ApplicationInfo appInfo);
2335 
2336     @Direct
getActivityIcon(ComponentName activityName)2337     Drawable getActivityIcon(ComponentName activityName);
2338 
2339     @Direct
loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo)2340     Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo);
2341 
2342     @Direct
getPackageArchiveInfo(String archiveFilePath, int flags)2343     PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags);
2344 
2345     @Accessor("mContext")
getContext()2346     Context getContext();
2347   }
2348 
2349   /** Returns the list of package names that were requested to be cleared. */
getClearedApplicationUserDataPackages()2350   public List<String> getClearedApplicationUserDataPackages() {
2351     return Collections.unmodifiableList(clearedApplicationUserDataPackages);
2352   }
2353 }
2354