1 package org.robolectric.shadows;
2 
3 import static android.content.IntentFilter.MATCH_CATEGORY_MASK;
4 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
5 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
6 import static android.content.pm.PackageManager.GET_META_DATA;
7 import static android.content.pm.PackageManager.GET_SIGNATURES;
8 import static android.content.pm.PackageManager.MATCH_ALL;
9 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
10 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
11 import static android.content.pm.PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
12 import static android.os.Build.VERSION_CODES.JELLY_BEAN;
13 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
14 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
15 import static android.os.Build.VERSION_CODES.KITKAT;
16 import static android.os.Build.VERSION_CODES.LOLLIPOP;
17 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1;
18 import static android.os.Build.VERSION_CODES.M;
19 import static android.os.Build.VERSION_CODES.N;
20 import static android.os.Build.VERSION_CODES.O;
21 import static android.os.Build.VERSION_CODES.O_MR1;
22 import static android.os.Build.VERSION_CODES.P;
23 import static android.os.Build.VERSION_CODES.Q;
24 import static android.os.Build.VERSION_CODES.R;
25 
26 import static org.robolectric.shadow.api.Shadow.invokeConstructor;
27 import static org.robolectric.util.ReflectionHelpers.ClassParameter.from;
28 
29 import android.annotation.DrawableRes;
30 import android.annotation.NonNull;
31 import android.annotation.Nullable;
32 import android.annotation.UserIdInt;
33 import android.app.ApplicationPackageManager;
34 import android.app.admin.DevicePolicyManager;
35 import android.content.ComponentName;
36 import android.content.Context;
37 import android.content.Intent;
38 import android.content.IntentFilter;
39 import android.content.IntentSender;
40 import android.content.pm.ActivityInfo;
41 import android.content.pm.ApplicationInfo;
42 import android.content.pm.ChangedPackages;
43 import android.content.pm.ComponentInfo;
44 import android.content.pm.FeatureInfo;
45 import android.content.pm.IPackageDataObserver;
46 import android.content.pm.IPackageDeleteObserver;
47 import android.content.pm.IPackageManager;
48 import android.content.pm.IPackageStatsObserver;
49 import android.content.pm.InstrumentationInfo;
50 import android.content.pm.IntentFilterVerificationInfo;
51 import android.content.pm.ModuleInfo;
52 import android.content.pm.PackageInfo;
53 import android.content.pm.PackageItemInfo;
54 import android.content.pm.PackageManager;
55 import android.content.pm.PackageManager.NameNotFoundException;
56 import android.content.pm.PackageParser;
57 import android.content.pm.PackageParser.Activity;
58 import android.content.pm.PackageParser.Component;
59 import android.content.pm.PackageParser.Package;
60 import android.content.pm.PackageParser.PermissionGroup;
61 import android.content.pm.PackageParser.Provider;
62 import android.content.pm.PackageParser.Service;
63 import android.content.pm.PackageStats;
64 import android.content.pm.PermissionGroupInfo;
65 import android.content.pm.PermissionInfo;
66 import android.content.pm.ProviderInfo;
67 import android.content.pm.ResolveInfo;
68 import android.content.pm.ServiceInfo;
69 import android.content.pm.VerifierDeviceIdentity;
70 import android.content.res.AssetManager;
71 import android.content.res.Resources;
72 import android.graphics.drawable.Drawable;
73 import android.net.Uri;
74 import android.os.Build.VERSION;
75 import android.os.Build.VERSION_CODES;
76 import android.os.Handler;
77 import android.os.Looper;
78 import android.os.Parcel;
79 import android.os.PersistableBundle;
80 import android.os.RemoteException;
81 import android.os.UserHandle;
82 import android.os.storage.VolumeInfo;
83 
84 import android.permission.IPermissionManager;
85 import android.telecom.TelecomManager;
86 import android.util.Pair;
87 import com.google.common.base.Function;
88 import java.io.File;
89 import java.util.ArrayList;
90 import java.util.Arrays;
91 import java.util.Collections;
92 import java.util.HashSet;
93 import java.util.Iterator;
94 import java.util.List;
95 import java.util.Map.Entry;
96 import java.util.Objects;
97 import java.util.Set;
98 import org.robolectric.RuntimeEnvironment;
99 import org.robolectric.annotation.HiddenApi;
100 import org.robolectric.annotation.Implementation;
101 import org.robolectric.annotation.Implements;
102 import org.robolectric.annotation.RealObject;
103 import org.robolectric.shadow.api.Shadow;
104 
105 @Implements(value = ApplicationPackageManager.class, isInAndroidSdk = false, looseSignatures = true)
106 public class ShadowApplicationPackageManager extends ShadowPackageManager {
107 
108   /** Package name of the Android platform. */
109   private static final String PLATFORM_PACKAGE_NAME = "android";
110 
111   /** MIME type of Android Packages (APKs). */
112   private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
113 
114   /** {@link Uri} scheme of installed apps. */
115   private static final String PACKAGE_SCHEME = "package";
116 
117   @RealObject private ApplicationPackageManager realObject;
118 
119   private Context context;
120 
121   @Implementation
__constructor__(Object contextImpl, Object pm)122   protected void __constructor__(Object contextImpl, Object pm) {
123     try {
124       invokeConstructor(
125           ApplicationPackageManager.class,
126           realObject,
127           from(Class.forName(ShadowContextImpl.CLASS_NAME), contextImpl),
128           from(IPackageManager.class, pm));
129     } catch (ClassNotFoundException e) {
130       throw new RuntimeException(e);
131     }
132     context = (Context) contextImpl;
133   }
134 
135   // BEGIN-INTERNAL
136   @Implementation(minSdk = R, maxSdk = R)
__constructor__( Object contextImpl, Object packageManager, Object permissionManager)137   protected void __constructor__(
138           Object contextImpl, Object packageManager, Object permissionManager) {
139     try {
140       invokeConstructor(
141           ApplicationPackageManager.class,
142           realObject,
143           from(Class.forName(ShadowContextImpl.CLASS_NAME), contextImpl),
144           from(IPackageManager.class, packageManager),
145           from(IPermissionManager.class, permissionManager));
146     } catch (ClassNotFoundException e) {
147       throw new RuntimeException(e);
148     }
149     context = (Context) contextImpl;
150   }
151   // END-INTERNAL
152 
153   @Implementation
getInstalledPackages(int flags)154   public List<PackageInfo> getInstalledPackages(int flags) {
155     List<PackageInfo> result = new ArrayList<>();
156     for (PackageInfo packageInfo : packageInfos.values()) {
157       String packageName = packageInfo.packageName;
158 
159       if (applicationEnabledSettingMap.get(packageName) == COMPONENT_ENABLED_STATE_DISABLED
160           && (flags & MATCH_UNINSTALLED_PACKAGES) != MATCH_UNINSTALLED_PACKAGES
161           && (flags & MATCH_DISABLED_COMPONENTS) != MATCH_DISABLED_COMPONENTS) {
162         continue;
163       }
164 
165       if (hiddenPackages.contains(packageName) && !isFlagSet(flags, MATCH_UNINSTALLED_PACKAGES)) {
166         continue;
167       }
168 
169       result.add(newPackageInfo(packageInfo));
170     }
171 
172     return result;
173   }
174 
175   @Implementation
getActivityInfo(ComponentName component, int flags)176   protected ActivityInfo getActivityInfo(ComponentName component, int flags)
177       throws NameNotFoundException {
178     String activityName = component.getClassName();
179     String packageName = component.getPackageName();
180     PackageInfo packageInfo = packageInfos.get(packageName);
181 
182     if (packageInfo != null) {
183       if (packageInfo.activities != null) {
184         for (ActivityInfo activity : packageInfo.activities) {
185           if (activityName.equals(activity.name)) {
186             ActivityInfo result = new ActivityInfo(activity);
187             applyFlagsToComponentInfo(result, flags);
188 
189             return result;
190           }
191         }
192       }
193 
194       // Activity is requested is not listed in the AndroidManifest.xml
195       ActivityInfo result = new ActivityInfo();
196       result.name = activityName;
197       result.packageName = packageName;
198       result.applicationInfo = new ApplicationInfo(packageInfo.applicationInfo);
199       return result;
200     }
201 
202     // TODO: Should throw a NameNotFoundException
203     // In the cases where an Activity from another package has been requested.
204     ActivityInfo result = new ActivityInfo();
205     result.name = activityName;
206     result.packageName = packageName;
207     result.applicationInfo = new ApplicationInfo();
208     result.applicationInfo.packageName = packageName;
209     result.applicationInfo.flags = ApplicationInfo.FLAG_INSTALLED;
210     return result;
211   }
212 
213   @Implementation
hasSystemFeature(String name)214   protected boolean hasSystemFeature(String name) {
215     return systemFeatureList.containsKey(name) ? systemFeatureList.get(name) : false;
216   }
217 
218   @Implementation
getComponentEnabledSetting(ComponentName componentName)219   protected int getComponentEnabledSetting(ComponentName componentName) {
220     ComponentState state = componentList.get(componentName);
221     return state != null ? state.newState : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
222   }
223 
224   @Implementation
getNameForUid(int uid)225   protected @Nullable String getNameForUid(int uid) {
226     return namesForUid.get(uid);
227   }
228 
229   @Implementation
getPackagesForUid(int uid)230   protected @Nullable String[] getPackagesForUid(int uid) {
231     String[] packageNames = packagesForUid.get(uid);
232     if (packageNames != null) {
233       return packageNames;
234     }
235 
236     Set<String> results = new HashSet<>();
237     for (PackageInfo packageInfo : packageInfos.values()) {
238       if (packageInfo.applicationInfo != null && packageInfo.applicationInfo.uid == uid) {
239         results.add(packageInfo.packageName);
240       }
241     }
242 
243     return results.isEmpty() ? null : results.toArray(new String[results.size()]);
244   }
245 
246   @Implementation
getApplicationEnabledSetting(String packageName)247   protected int getApplicationEnabledSetting(String packageName) {
248     try {
249       getPackageInfo(packageName, -1);
250     } catch (NameNotFoundException e) {
251       throw new IllegalArgumentException(e);
252     }
253 
254     return applicationEnabledSettingMap.get(packageName);
255   }
256 
257   @Implementation
getProviderInfo(ComponentName component, int flags)258   protected ProviderInfo getProviderInfo(ComponentName component, int flags)
259       throws NameNotFoundException {
260     String packageName = component.getPackageName();
261 
262     PackageInfo packageInfo = packageInfos.get(packageName);
263     if (packageInfo != null && packageInfo.providers != null) {
264       for (ProviderInfo provider : packageInfo.providers) {
265         if (resolvePackageName(packageName, component).equals(provider.name)) {
266           ProviderInfo result = new ProviderInfo(provider);
267           applyFlagsToComponentInfo(result, flags);
268           return result;
269         }
270       }
271     }
272 
273     throw new NameNotFoundException("Package not found: " + packageName);
274   }
275 
276   @Implementation
setComponentEnabledSetting(ComponentName componentName, int newState, int flags)277   protected void setComponentEnabledSetting(ComponentName componentName, int newState, int flags) {
278     componentList.put(componentName, new ComponentState(newState, flags));
279   }
280 
281   @Implementation
setApplicationEnabledSetting(String packageName, int newState, int flags)282   protected void setApplicationEnabledSetting(String packageName, int newState, int flags) {
283     applicationEnabledSettingMap.put(packageName, newState);
284   }
285 
286   @Implementation
resolveActivity(Intent intent, int flags)287   protected ResolveInfo resolveActivity(Intent intent, int flags) {
288     HashSet<ComponentName> preferredComponents = new HashSet<>();
289 
290     for (Entry<IntentFilterWrapper, ComponentName> preferred : preferredActivities.entrySet()) {
291       if ((preferred.getKey().getFilter().match(context.getContentResolver(), intent, false, "robo")
292               & MATCH_CATEGORY_MASK)
293           != 0) {
294         preferredComponents.add(preferred.getValue());
295       }
296     }
297     List<ResolveInfo> candidates = queryIntentActivities(intent, flags);
298 
299     return candidates.isEmpty()
300         ? null
301         : Collections.max(candidates, new ResolveInfoComparator(preferredComponents));
302   }
303 
304   @Implementation
resolveContentProvider(String name, int flags)305   protected ProviderInfo resolveContentProvider(String name, int flags) {
306     if (name == null) {
307       return null;
308     }
309     for (PackageInfo packageInfo : packageInfos.values()) {
310       if (packageInfo.providers == null) continue;
311 
312       for (ProviderInfo providerInfo : packageInfo.providers) {
313         if (name.equals(providerInfo.authority)) { // todo: support multiple authorities
314           return new ProviderInfo(providerInfo);
315         }
316       }
317     }
318     return null;
319   }
320 
321   @Implementation(minSdk = LOLLIPOP)
resolveContentProviderAsUser( String name, int flags, @UserIdInt int userId)322   protected ProviderInfo resolveContentProviderAsUser(
323       String name, int flags, @UserIdInt int userId) {
324     return null;
325   }
326 
327   @Implementation
getPackageInfo(String packageName, int flags)328   protected synchronized PackageInfo getPackageInfo(String packageName, int flags)
329       throws NameNotFoundException {
330     PackageInfo info = packageInfos.get(packageName);
331     if (info != null) {
332       if (applicationEnabledSettingMap.get(packageName) == COMPONENT_ENABLED_STATE_DISABLED
333           && (flags & MATCH_UNINSTALLED_PACKAGES) != MATCH_UNINSTALLED_PACKAGES
334           && (flags & MATCH_DISABLED_COMPONENTS) != MATCH_DISABLED_COMPONENTS) {
335         throw new NameNotFoundException("Package is disabled, can't find");
336       }
337       if (hiddenPackages.contains(packageName) && !isFlagSet(flags, MATCH_UNINSTALLED_PACKAGES)) {
338         throw new NameNotFoundException("Package is hidden, can't find");
339       }
340       return newPackageInfo(info);
341     } else {
342       throw new NameNotFoundException(packageName);
343     }
344   }
345 
346   // There is no copy constructor for PackageInfo
newPackageInfo(PackageInfo orig)347   private static PackageInfo newPackageInfo(PackageInfo orig) {
348     Parcel parcel = Parcel.obtain();
349     orig.writeToParcel(parcel, 0);
350     parcel.setDataPosition(0);
351     return PackageInfo.CREATOR.createFromParcel(parcel);
352   }
353 
354   @Implementation
queryIntentServices(Intent intent, int flags)355   protected List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
356     List<ResolveInfo> result = new ArrayList<>();
357     List<ResolveInfo> resolveInfoList = queryOverriddenIntents(intent, flags);
358     if (!resolveInfoList.isEmpty()) {
359       result.addAll(
360           filterResolvedComponent(
361               resolveInfoList, flags, (resolveInfo) -> resolveInfo.serviceInfo));
362     }
363 
364     if (isExplicitIntent(intent)) {
365       ResolveInfo resolvedService = resolveServiceForExplicitIntent(intent);
366       if (resolvedService != null) {
367         result.addAll(
368             filterResolvedComponent(
369                 Arrays.asList(resolvedService), flags, (resolveInfo) -> resolveInfo.serviceInfo));
370       }
371     } else {
372       result.addAll(
373           filterResolvedComponent(
374               queryImplicitIntentServices(intent),
375               flags,
376               (resolveInfo) -> resolveInfo.serviceInfo));
377     }
378     return result;
379   }
380 
filterResolvedComponent( List<ResolveInfo> resolveInfoList, int flags, Function<ResolveInfo, ComponentInfo> componentInfoFn)381   private List<ResolveInfo> filterResolvedComponent(
382       List<ResolveInfo> resolveInfoList,
383       int flags,
384       Function<ResolveInfo, ComponentInfo> componentInfoFn) {
385     // If the flag is set, no further filtering will happen.
386     if (isFlagSet(flags, PackageManager.MATCH_ALL)) {
387       return resolveInfoList;
388     }
389     // Create a copy of the list for filtering
390     resolveInfoList = new ArrayList<>(resolveInfoList);
391 
392     for (Iterator<ResolveInfo> iterator = resolveInfoList.iterator(); iterator.hasNext(); ) {
393       ResolveInfo resolveInfo = iterator.next();
394       ComponentInfo componentInfo = componentInfoFn.apply(resolveInfo);
395 
396       boolean hasSomeComponentInfo =
397           resolveInfo.activityInfo != null
398               || resolveInfo.serviceInfo != null
399               || (VERSION.SDK_INT >= VERSION_CODES.KITKAT && resolveInfo.providerInfo != null);
400       if (componentInfo == null && hasSomeComponentInfo) {
401         // wrong type of component. For backward compatibility we keep those entries that doesn't
402         // have any component.
403         iterator.remove();
404         continue;
405       }
406 
407       if (isFlagSet(flags, PackageManager.MATCH_SYSTEM_ONLY)) {
408         if (componentInfo == null || componentInfo.applicationInfo == null) {
409           // TODO: for backwards compatibility just skip filtering. In future should just remove
410           // invalid resolve infos from list
411           iterator.remove();
412           continue;
413         } else {
414           final int applicationFlags = componentInfo.applicationInfo.flags;
415           if ((applicationFlags & ApplicationInfo.FLAG_SYSTEM) != ApplicationInfo.FLAG_SYSTEM) {
416             iterator.remove();
417             continue;
418           }
419         }
420       }
421       if (!isFlagSet(flags, PackageManager.MATCH_DISABLED_COMPONENTS)
422           && resolveInfo != null
423           && isValidComponentInfo(componentInfo)) {
424         ComponentName componentName =
425             new ComponentName(componentInfo.applicationInfo.packageName, componentInfo.name);
426         if ((getComponentEnabledSetting(componentName)
427                 & PackageManager.COMPONENT_ENABLED_STATE_DISABLED)
428             != 0) {
429           iterator.remove();
430           continue;
431         }
432       }
433       if (!isFlagSet(flags, MATCH_UNINSTALLED_PACKAGES)
434           && resolveInfo != null
435           && isValidComponentInfo(componentInfo)
436           && hiddenPackages.contains(componentInfo.applicationInfo.packageName)) {
437         iterator.remove();
438         continue;
439       }
440     }
441     return resolveInfoList;
442   }
443 
isFlagSet(int flags, int matchFlag)444   private static boolean isFlagSet(int flags, int matchFlag) {
445     return (flags & matchFlag) == matchFlag;
446   }
447 
isValidComponentInfo(ComponentInfo componentInfo)448   private static boolean isValidComponentInfo(ComponentInfo componentInfo) {
449     return componentInfo != null
450         && componentInfo.applicationInfo != null
451         && componentInfo.applicationInfo.packageName != null
452         && componentInfo.name != null;
453   }
454 
455   /** Behaves as {@link #queryIntentServices(Intent, int)} and currently ignores userId. */
456   @Implementation(minSdk = JELLY_BEAN_MR1)
queryIntentServicesAsUser(Intent intent, int flags, int userId)457   protected List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) {
458     return queryIntentServices(intent, flags);
459   }
460 
461   @Implementation
queryIntentActivities(Intent intent, int flags)462   protected List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
463     List<ResolveInfo> result = new ArrayList<>();
464     List<ResolveInfo> resolveInfoList = queryOverriddenIntents(intent, flags);
465     if (!resolveInfoList.isEmpty()) {
466       result.addAll(
467           filterResolvedComponent(
468               resolveInfoList, flags, (resolveInfo) -> resolveInfo.activityInfo));
469     }
470 
471     if (isExplicitIntent(intent)) {
472       ResolveInfo resolvedActivity = resolveActivityForExplicitIntent(intent);
473       if (resolvedActivity != null) {
474         result.addAll(
475             filterResolvedComponent(
476                 Arrays.asList(resolvedActivity), flags, (resolveInfo) -> resolveInfo.activityInfo));
477       }
478     } else {
479       result.addAll(
480           filterResolvedComponent(
481               queryImplicitIntentActivities(intent),
482               flags,
483               (resolveInfo) -> resolveInfo.activityInfo));
484     }
485     return result;
486   }
487 
488   /** Behaves as {@link #queryIntentActivities(Intent, int)} and currently ignores userId. */
489   @Implementation(minSdk = JELLY_BEAN_MR1)
queryIntentActivitiesAsUser(Intent intent, int flags, int userId)490   protected List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId) {
491     return queryIntentActivities(intent, flags);
492   }
493 
494   /** Returns true if intent has specified a specific component. */
isExplicitIntent(Intent intent)495   private static boolean isExplicitIntent(Intent intent) {
496     return getComponentForIntent(intent) != null;
497   }
498 
resolveActivityForExplicitIntent(Intent intent)499   private ResolveInfo resolveActivityForExplicitIntent(Intent intent) {
500     ComponentName component = getComponentForIntent(intent);
501     for (Package appPackage : packages.values()) {
502       Activity activity = findMatchingComponent(component, appPackage.activities);
503       if (activity != null) {
504         return buildResolveInfo(activity);
505       }
506     }
507     return null;
508   }
509 
resolveServiceForExplicitIntent(Intent intent)510   private ResolveInfo resolveServiceForExplicitIntent(Intent intent) {
511     ComponentName component = getComponentForIntent(intent);
512     for (Package appPackage : packages.values()) {
513       Service service = findMatchingComponent(component, appPackage.services);
514       if (service != null) {
515         return buildResolveInfo(service);
516       }
517     }
518     return null;
519   }
520 
resolveReceiverForExplicitIntent(Intent intent)521   private ResolveInfo resolveReceiverForExplicitIntent(Intent intent) {
522     ComponentName component = getComponentForIntent(intent);
523     for (Package appPackage : packages.values()) {
524       Activity receiver = findMatchingComponent(component, appPackage.receivers);
525       if (receiver != null) {
526         return buildResolveInfo(receiver);
527       }
528     }
529     return null;
530   }
531 
resolveContentProviderForExplicitIntent(Intent intent)532   private ResolveInfo resolveContentProviderForExplicitIntent(Intent intent) {
533     ComponentName component = getComponentForIntent(intent);
534     for (Package appPackage : packages.values()) {
535       Provider provider = findMatchingComponent(component, appPackage.providers);
536       if (provider != null) {
537         return buildResolveInfo(provider);
538       }
539     }
540     return null;
541   }
542 
findMatchingComponent( ComponentName componentName, List<T> components)543   private static <T extends Component> T findMatchingComponent(
544       ComponentName componentName, List<T> components) {
545     for (T component : components) {
546       if (componentName.equals(component.getComponentName())) {
547         return component;
548       }
549     }
550     return null;
551   }
552 
getComponentForIntent(Intent intent)553   private static ComponentName getComponentForIntent(Intent intent) {
554     ComponentName component = intent.getComponent();
555     if (component == null) {
556       if (intent.getSelector() != null) {
557         intent = intent.getSelector();
558         component = intent.getComponent();
559       }
560     }
561     return component;
562   }
563 
queryImplicitIntentContentProviders(Intent intent)564   private List<ResolveInfo> queryImplicitIntentContentProviders(Intent intent) {
565     List<ResolveInfo> resolveInfoList = new ArrayList<>();
566 
567     for (Package appPackage : packages.values()) {
568       if (intent.getPackage() == null || intent.getPackage().equals(appPackage.packageName)) {
569         for (Provider provider : appPackage.providers) {
570           IntentFilter intentFilter = matchIntentFilter(intent, provider.intents);
571           if (intentFilter != null) {
572             resolveInfoList.add(buildResolveInfo(provider));
573           }
574         }
575       }
576     }
577 
578     return resolveInfoList;
579   }
580 
queryImplicitIntentActivities(Intent intent)581   private List<ResolveInfo> queryImplicitIntentActivities(Intent intent) {
582     List<ResolveInfo> resolveInfoList = new ArrayList<>();
583 
584     for (Package appPackage : packages.values()) {
585       if (intent.getPackage() == null || intent.getPackage().equals(appPackage.packageName)) {
586         for (Activity activity : appPackage.activities) {
587           IntentFilter intentFilter = matchIntentFilter(intent, activity.intents);
588           if (intentFilter != null) {
589             resolveInfoList.add(buildResolveInfo(activity, intentFilter));
590           }
591         }
592       }
593     }
594 
595     return resolveInfoList;
596   }
597 
queryImplicitIntentServices(Intent intent)598   private List<ResolveInfo> queryImplicitIntentServices(Intent intent) {
599     List<ResolveInfo> resolveInfoList = new ArrayList<>();
600 
601     for (Package appPackage : packages.values()) {
602       if (intent.getPackage() == null || intent.getPackage().equals(appPackage.packageName)) {
603         for (Service service : appPackage.services) {
604           IntentFilter intentFilter = matchIntentFilter(intent, service.intents);
605           if (intentFilter != null) {
606             resolveInfoList.add(buildResolveInfo(service, intentFilter));
607           }
608         }
609       }
610     }
611 
612     return resolveInfoList;
613   }
614 
queryImplicitIntentReceivers(Intent intent)615   private List<ResolveInfo> queryImplicitIntentReceivers(Intent intent) {
616     List<ResolveInfo> resolveInfoList = new ArrayList<>();
617 
618     for (Package appPackage : packages.values()) {
619       if (intent.getPackage() == null || intent.getPackage().equals(appPackage.packageName)) {
620         for (Activity activity : appPackage.receivers) {
621           IntentFilter intentFilter = matchIntentFilter(intent, activity.intents);
622           if (intentFilter != null) {
623             resolveInfoList.add(buildResolveInfo(activity, intentFilter));
624           }
625         }
626       }
627     }
628 
629     return resolveInfoList;
630   }
631 
buildResolveInfo(Activity activity)632   static ResolveInfo buildResolveInfo(Activity activity) {
633     ResolveInfo resolveInfo = buildResolveInfo(activity.info);
634     resolveInfo.activityInfo = activity.info;
635     return resolveInfo;
636   }
637 
buildResolveInfo(Service service)638   static ResolveInfo buildResolveInfo(Service service) {
639     ResolveInfo resolveInfo = buildResolveInfo(service.info);
640     resolveInfo.serviceInfo = service.info;
641     return resolveInfo;
642   }
643 
buildResolveInfo(Provider provider)644   static ResolveInfo buildResolveInfo(Provider provider) {
645     ResolveInfo resolveInfo = buildResolveInfo(provider.info);
646     resolveInfo.providerInfo = provider.info;
647     return resolveInfo;
648   }
649 
buildResolveInfo(ComponentInfo componentInfo)650   private static ResolveInfo buildResolveInfo(ComponentInfo componentInfo) {
651     ResolveInfo resolveInfo = new ResolveInfo();
652     resolveInfo.resolvePackageName = componentInfo.applicationInfo.packageName;
653     return resolveInfo;
654   }
655 
buildResolveInfo(Activity activity, IntentFilter intentFilter)656   static ResolveInfo buildResolveInfo(Activity activity, IntentFilter intentFilter) {
657     ResolveInfo info = buildResolveInfo(activity);
658     info.isDefault = intentFilter.hasCategory("Intent.CATEGORY_DEFAULT");
659     info.filter = new IntentFilter(intentFilter);
660     return info;
661   }
662 
buildResolveInfo(Service service, IntentFilter intentFilter)663   static ResolveInfo buildResolveInfo(Service service, IntentFilter intentFilter) {
664     ResolveInfo info = buildResolveInfo(service);
665     info.isDefault = intentFilter.hasCategory("Intent.CATEGORY_DEFAULT");
666     info.serviceInfo = service.info;
667     info.filter = new IntentFilter(intentFilter);
668     return info;
669   }
670 
671   @Implementation
checkPermission(String permName, String pkgName)672   protected int checkPermission(String permName, String pkgName) {
673     PackageInfo permissionsInfo = packageInfos.get(pkgName);
674     if (permissionsInfo == null || permissionsInfo.requestedPermissions == null) {
675       return PackageManager.PERMISSION_DENIED;
676     }
677 
678     String permission;
679     for (int i = 0; i < permissionsInfo.requestedPermissions.length; i++) {
680       permission = permissionsInfo.requestedPermissions[i];
681       if (permission != null && permission.equals(permName)) {
682         // The package requests this permission. Now check if it's been granted to the package.
683         if (isGrantedForBackwardsCompatibility(pkgName, permissionsInfo)) {
684           return PackageManager.PERMISSION_GRANTED;
685         }
686 
687         if ((permissionsInfo.requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED)
688             == REQUESTED_PERMISSION_GRANTED) {
689           return PackageManager.PERMISSION_GRANTED;
690         }
691       }
692     }
693 
694     return PackageManager.PERMISSION_DENIED;
695   }
696 
697   /**
698    * Returns whether a permission should be treated as granted to the package for backward
699    * compatibility reasons.
700    *
701    * <p>Before Robolectric 4.0 the ShadowPackageManager treated every requested permission as
702    * automatically granted. 4.0 changes this behavior, and only treats a permission as granted if
703    * PackageInfo.requestedPermissionFlags[permissionIndex] & REQUESTED_PERMISSION_GRANTED ==
704    * REQUESTED_PERMISSION_GRANTED which matches the real PackageManager's behavior.
705    *
706    * <p>Since many existing tests didn't set the requestedPermissionFlags on their {@code
707    * PackageInfo} objects, but assumed that all permissions are granted, we auto-grant all
708    * permissions if the requestedPermissionFlags is not set. If the requestedPermissionFlags is set,
709    * we assume that the test is configuring the permission grant state, and we don't override this
710    * setting.
711    */
isGrantedForBackwardsCompatibility(String pkgName, PackageInfo permissionsInfo)712   private boolean isGrantedForBackwardsCompatibility(String pkgName, PackageInfo permissionsInfo) {
713     // Note: it might be cleaner to auto-grant these permissions when the package is added to the
714     // PackageManager. But many existing tests modify the requested permissions _after_ adding the
715     // package to the PackageManager, without updating the requestedPermissionsFlags.
716     return permissionsInfo.requestedPermissionsFlags == null
717         // Robolectric uses the PackageParser to create the current test package's PackageInfo from
718         // the manifest XML. The parser populates the requestedPermissionsFlags, but doesn't grant
719         // the permissions. Several tests rely on the test package being granted all permissions, so
720         // we treat this as a special case.
721         || pkgName.equals(RuntimeEnvironment.application.getPackageName());
722   }
723 
724   @Implementation
getReceiverInfo(ComponentName className, int flags)725   protected ActivityInfo getReceiverInfo(ComponentName className, int flags)
726       throws NameNotFoundException {
727     String packageName = className.getPackageName();
728 
729     PackageInfo packageInfo = packageInfos.get(packageName);
730     if (packageInfo != null && packageInfo.receivers != null) {
731       for (ActivityInfo receiver : packageInfo.receivers) {
732         if (resolvePackageName(packageName, className).equals(receiver.name)) {
733           ActivityInfo result = new ActivityInfo(receiver);
734           applyFlagsToComponentInfo(result, flags);
735           return result;
736         }
737       }
738     }
739 
740     return null;
741   }
742 
743   @Implementation
queryBroadcastReceivers(Intent intent, int flags)744   protected List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
745     List<ResolveInfo> result = new ArrayList<>();
746     List<ResolveInfo> resolveInfoList = queryOverriddenIntents(intent, flags);
747     if (!resolveInfoList.isEmpty()) {
748       result.addAll(
749           filterResolvedComponent(
750               resolveInfoList, flags, (resolveInfo) -> resolveInfo.activityInfo));
751     }
752 
753     if (isExplicitIntent(intent)) {
754       ResolveInfo resolvedReceiver = resolveReceiverForExplicitIntent(intent);
755       if (resolvedReceiver != null) {
756         result.addAll(
757             filterResolvedComponent(
758                 Arrays.asList(resolvedReceiver), flags, (resolveInfo) -> resolveInfo.activityInfo));
759       }
760     } else {
761       result.addAll(
762           filterResolvedComponent(
763               queryImplicitIntentReceivers(intent),
764               flags,
765               (resolveInfo) -> resolveInfo.activityInfo));
766     }
767     return result;
768   }
769 
matchIntentFilter( Intent intent, ArrayList<? extends PackageParser.IntentInfo> intentFilters)770   private static IntentFilter matchIntentFilter(
771       Intent intent, ArrayList<? extends PackageParser.IntentInfo> intentFilters) {
772     for (PackageParser.IntentInfo intentInfo : intentFilters) {
773       if (intentInfo.match(
774               intent.getAction(),
775               intent.getType(),
776               intent.getScheme(),
777               intent.getData(),
778               intent.getCategories(),
779               "ShadowPackageManager")
780           >= 0) {
781         return intentInfo;
782       }
783     }
784     return null;
785   }
786 
787   @Implementation
resolveService(Intent intent, int flags)788   protected ResolveInfo resolveService(Intent intent, int flags) {
789     List<ResolveInfo> candidates = queryIntentServices(intent, flags);
790     return candidates.isEmpty() ? null : candidates.get(0);
791   }
792 
793   @Implementation
getServiceInfo(ComponentName className, int flags)794   protected ServiceInfo getServiceInfo(ComponentName className, int flags)
795       throws NameNotFoundException {
796     String packageName = className.getPackageName();
797     PackageInfo packageInfo = packageInfos.get(packageName);
798 
799     if (packageInfo != null) {
800       String serviceName = className.getClassName();
801       if (packageInfo.services != null) {
802         for (ServiceInfo service : packageInfo.services) {
803           if (serviceName.equals(service.name)) {
804             ServiceInfo result = new ServiceInfo(service);
805             applyFlagsToComponentInfo(result, flags);
806             result.applicationInfo = new ApplicationInfo(service.applicationInfo);
807             if (result.processName == null) {
808               result.processName = result.applicationInfo.processName;
809             }
810             return result;
811           }
812         }
813       }
814       throw new NameNotFoundException(serviceName);
815     }
816     return null;
817   }
818 
applyFlagsToComponentInfo(ComponentInfo result, int flags)819   private void applyFlagsToComponentInfo(ComponentInfo result, int flags)
820       throws NameNotFoundException {
821     if ((flags & GET_META_DATA) == 0) {
822       result.metaData = null;
823     }
824     if ((flags & MATCH_ALL) != 0) {
825       return;
826     }
827   }
828 
829   @Implementation
getResourcesForApplication(@onNull ApplicationInfo applicationInfo)830   protected Resources getResourcesForApplication(@NonNull ApplicationInfo applicationInfo)
831       throws PackageManager.NameNotFoundException {
832     return getResourcesForApplication(applicationInfo.packageName);
833   }
834 
835   @Implementation
getInstalledApplications(int flags)836   protected List<ApplicationInfo> getInstalledApplications(int flags) {
837     List<ApplicationInfo> result = new ArrayList<>();
838 
839     for (PackageInfo packageInfo : packageInfos.values()) {
840       result.add(packageInfo.applicationInfo);
841     }
842     return result;
843   }
844 
845   @Implementation
getInstallerPackageName(String packageName)846   protected String getInstallerPackageName(String packageName) {
847     return packageInstallerMap.get(packageName);
848   }
849 
850   @Implementation
getPermissionInfo(String name, int flags)851   protected PermissionInfo getPermissionInfo(String name, int flags) throws NameNotFoundException {
852     PermissionInfo permissionInfo = extraPermissions.get(name);
853     if (permissionInfo != null) {
854       return permissionInfo;
855     }
856 
857     for (PackageInfo packageInfo : packageInfos.values()) {
858       if (packageInfo.permissions != null) {
859         for (PermissionInfo permission : packageInfo.permissions) {
860           if (name.equals(permission.name)) {
861             return createCopyPermissionInfo(permission, flags);
862           }
863         }
864       }
865     }
866 
867     throw new NameNotFoundException(name);
868   }
869 
870   @Implementation(minSdk = M)
shouldShowRequestPermissionRationale(String permission)871   protected boolean shouldShowRequestPermissionRationale(String permission) {
872     return permissionRationaleMap.containsKey(permission)
873         ? permissionRationaleMap.get(permission)
874         : false;
875   }
876 
877   @Implementation
getSystemAvailableFeatures()878   protected FeatureInfo[] getSystemAvailableFeatures() {
879     return systemAvailableFeatures.isEmpty()
880         ? null
881         : systemAvailableFeatures.toArray(new FeatureInfo[systemAvailableFeatures.size()]);
882   }
883 
884   @Implementation
verifyPendingInstall(int id, int verificationCode)885   protected void verifyPendingInstall(int id, int verificationCode) {
886     if (verificationResults.containsKey(id)) {
887       throw new IllegalStateException("Multiple verifications for id=" + id);
888     }
889     verificationResults.put(id, verificationCode);
890   }
891 
892   @Implementation(minSdk = JELLY_BEAN_MR1)
extendVerificationTimeout( int id, int verificationCodeAtTimeout, long millisecondsToDelay)893   protected void extendVerificationTimeout(
894       int id, int verificationCodeAtTimeout, long millisecondsToDelay) {
895     verificationTimeoutExtension.put(id, millisecondsToDelay);
896   }
897 
898   @Override
899   @Implementation(maxSdk = LOLLIPOP_MR1)
freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer)900   protected void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer) {}
901 
902   @Implementation(minSdk = M)
freeStorageAndNotify( String volumeUuid, long freeStorageSize, IPackageDataObserver observer)903   protected void freeStorageAndNotify(
904       String volumeUuid, long freeStorageSize, IPackageDataObserver observer) {}
905 
906   @Implementation
setInstallerPackageName(String targetPackage, String installerPackageName)907   protected void setInstallerPackageName(String targetPackage, String installerPackageName) {
908     packageInstallerMap.put(targetPackage, installerPackageName);
909   }
910 
911   @Implementation(minSdk = KITKAT)
queryIntentContentProviders(Intent intent, int flags)912   protected List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags) {
913     List<ResolveInfo> result = new ArrayList<>();
914     List<ResolveInfo> resolveInfoList = queryOverriddenIntents(intent, flags);
915     if (!resolveInfoList.isEmpty()) {
916       result.addAll(
917           filterResolvedComponent(
918               resolveInfoList, flags, (resolveInfo) -> resolveInfo.providerInfo));
919     }
920 
921     if (isExplicitIntent(intent)) {
922       ResolveInfo resolvedProvider = resolveContentProviderForExplicitIntent(intent);
923       if (resolvedProvider != null) {
924         result.addAll(
925             filterResolvedComponent(
926                 Arrays.asList(resolvedProvider), flags, (resolveInfo) -> resolveInfo.providerInfo));
927       }
928     } else {
929       result.addAll(
930           filterResolvedComponent(
931               queryImplicitIntentContentProviders(intent),
932               flags,
933               (resolveInfo) -> resolveInfo.providerInfo));
934     }
935     return result;
936   }
937 
938   @Implementation(minSdk = KITKAT)
queryIntentContentProvidersAsUser( Intent intent, int flags, int userId)939   protected List<ResolveInfo> queryIntentContentProvidersAsUser(
940       Intent intent, int flags, int userId) {
941     return Collections.emptyList();
942   }
943 
944   @Implementation(minSdk = M)
getPermissionControllerPackageName()945   protected String getPermissionControllerPackageName() {
946     return null;
947   }
948 
949   @Implementation(maxSdk = JELLY_BEAN)
getPackageSizeInfo(Object pkgName, Object observer)950   protected void getPackageSizeInfo(Object pkgName, Object observer) {
951     final PackageStats packageStats = packageStatsMap.get((String) pkgName);
952     new Handler(Looper.getMainLooper())
953         .post(
954             () -> {
955               try {
956                 ((IPackageStatsObserver) observer)
957                     .onGetStatsCompleted(packageStats, packageStats != null);
958               } catch (RemoteException remoteException) {
959                 remoteException.rethrowFromSystemServer();
960               }
961             });
962   }
963 
964   @Implementation(minSdk = JELLY_BEAN_MR1, maxSdk = M)
getPackageSizeInfo(Object pkgName, Object uid, final Object observer)965   protected void getPackageSizeInfo(Object pkgName, Object uid, final Object observer) {
966     final PackageStats packageStats = packageStatsMap.get((String) pkgName);
967     new Handler(Looper.getMainLooper())
968         .post(
969             () -> {
970               try {
971                 ((IPackageStatsObserver) observer)
972                     .onGetStatsCompleted(packageStats, packageStats != null);
973               } catch (RemoteException remoteException) {
974                 remoteException.rethrowFromSystemServer();
975               }
976             });
977   }
978 
979   @Implementation(minSdk = N)
getPackageSizeInfoAsUser(Object pkgName, Object uid, final Object observer)980   protected void getPackageSizeInfoAsUser(Object pkgName, Object uid, final Object observer) {
981     final PackageStats packageStats = packageStatsMap.get((String) pkgName);
982     new Handler(Looper.getMainLooper())
983         .post(
984             () -> {
985               try {
986                 ((IPackageStatsObserver) observer)
987                     .onGetStatsCompleted(packageStats, packageStats != null);
988               } catch (RemoteException remoteException) {
989                 remoteException.rethrowFromSystemServer();
990               }
991             });
992   }
993 
994   @Implementation
deletePackage(String packageName, IPackageDeleteObserver observer, int flags)995   protected void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
996     pendingDeleteCallbacks.put(packageName, observer);
997   }
998 
999   @Implementation
currentToCanonicalPackageNames(String[] names)1000   protected String[] currentToCanonicalPackageNames(String[] names) {
1001     String[] out = new String[names.length];
1002     for (int i = names.length - 1; i >= 0; i--) {
1003       if (currentToCanonicalNames.containsKey(names[i])) {
1004         out[i] = currentToCanonicalNames.get(names[i]);
1005       } else {
1006         out[i] = names[i];
1007       }
1008     }
1009     return out;
1010   }
1011 
1012   @Implementation
isSafeMode()1013   protected boolean isSafeMode() {
1014     return false;
1015   }
1016 
1017   @Implementation
getApplicationIcon(String packageName)1018   protected Drawable getApplicationIcon(String packageName) throws NameNotFoundException {
1019     return applicationIcons.get(packageName);
1020   }
1021 
1022   @Implementation
getApplicationIcon(ApplicationInfo info)1023   protected Drawable getApplicationIcon(ApplicationInfo info) throws NameNotFoundException {
1024     return getApplicationIcon(info.packageName);
1025   }
1026 
1027   @Implementation(minSdk = LOLLIPOP)
getUserBadgeForDensity(UserHandle userHandle, int i)1028   protected Drawable getUserBadgeForDensity(UserHandle userHandle, int i) {
1029     return null;
1030   }
1031 
1032   @Implementation
checkSignatures(String pkg1, String pkg2)1033   protected int checkSignatures(String pkg1, String pkg2) {
1034     try {
1035       PackageInfo packageInfo1 = getPackageInfo(pkg1, GET_SIGNATURES);
1036       PackageInfo packageInfo2 = getPackageInfo(pkg2, GET_SIGNATURES);
1037       return compareSignature(packageInfo1.signatures, packageInfo2.signatures);
1038     } catch (NameNotFoundException e) {
1039       return SIGNATURE_UNKNOWN_PACKAGE;
1040     }
1041   }
1042 
1043   @Implementation
checkSignatures(int uid1, int uid2)1044   protected int checkSignatures(int uid1, int uid2) {
1045     return 0;
1046   }
1047 
1048   @Implementation
queryPermissionsByGroup(String group, int flags)1049   protected List<PermissionInfo> queryPermissionsByGroup(String group, int flags)
1050       throws NameNotFoundException {
1051     List<PermissionInfo> result = new ArrayList<>();
1052     for (PermissionInfo permissionInfo : extraPermissions.values()) {
1053       if (Objects.equals(permissionInfo.group, group)) {
1054         result.add(permissionInfo);
1055       }
1056     }
1057 
1058     for (PackageInfo packageInfo : packageInfos.values()) {
1059       if (packageInfo.permissions != null) {
1060         for (PermissionInfo permission : packageInfo.permissions) {
1061           if (Objects.equals(group, permission.group)) {
1062             result.add(createCopyPermissionInfo(permission, flags));
1063           }
1064         }
1065       }
1066     }
1067 
1068     if (result.isEmpty()) {
1069       throw new NameNotFoundException(group);
1070     }
1071 
1072     return result;
1073   }
1074 
createCopyPermissionInfo(PermissionInfo src, int flags)1075   private static PermissionInfo createCopyPermissionInfo(PermissionInfo src, int flags) {
1076     PermissionInfo matchedPermission = new PermissionInfo(src);
1077     if ((flags & GET_META_DATA) != GET_META_DATA) {
1078       matchedPermission.metaData = null;
1079     }
1080     return matchedPermission;
1081   }
1082 
1083   @Implementation
getLaunchIntentForPackage(String packageName)1084   protected Intent getLaunchIntentForPackage(String packageName) {
1085     Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
1086     intentToResolve.addCategory(Intent.CATEGORY_INFO);
1087     intentToResolve.setPackage(packageName);
1088     List<ResolveInfo> ris = queryIntentActivities(intentToResolve, 0);
1089 
1090     if (ris == null || ris.isEmpty()) {
1091       intentToResolve.removeCategory(Intent.CATEGORY_INFO);
1092       intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
1093       intentToResolve.setPackage(packageName);
1094       ris = queryIntentActivities(intentToResolve, 0);
1095     }
1096     if (ris == null || ris.isEmpty()) {
1097       return null;
1098     }
1099     Intent intent = new Intent(intentToResolve);
1100     intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1101     intent.setClassName(packageName, ris.get(0).activityInfo.name);
1102     return intent;
1103   }
1104 
1105   ////////////////////////////
1106 
1107   @Implementation(minSdk = N)
getPackageInfoAsUser(String packageName, int flags, int userId)1108   protected PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId)
1109       throws NameNotFoundException {
1110     return getPackageInfo(packageName, flags);
1111   }
1112 
1113   @Implementation
canonicalToCurrentPackageNames(String[] names)1114   protected String[] canonicalToCurrentPackageNames(String[] names) {
1115     return new String[0];
1116   }
1117 
1118   @Implementation
getPackageGids(String packageName)1119   protected int[] getPackageGids(String packageName) throws NameNotFoundException {
1120     return new int[0];
1121   }
1122 
1123   @Implementation(minSdk = N)
getPackageGids(String packageName, int flags)1124   protected int[] getPackageGids(String packageName, int flags) throws NameNotFoundException {
1125     return null;
1126   }
1127 
1128   @Implementation(minSdk = JELLY_BEAN_MR2)
getPackageUid(String packageName, int flags)1129   protected int getPackageUid(String packageName, int flags) throws NameNotFoundException {
1130     Integer uid = uidForPackage.get(packageName);
1131     if (uid == null) {
1132       throw new NameNotFoundException(packageName);
1133     }
1134     return uid;
1135   }
1136 
1137   @Implementation(minSdk = N)
getPackageUidAsUser(String packageName, int userId)1138   protected int getPackageUidAsUser(String packageName, int userId) throws NameNotFoundException {
1139     return 0;
1140   }
1141 
1142   @Implementation(minSdk = N)
getPackageUidAsUser(String packageName, int flags, int userId)1143   protected int getPackageUidAsUser(String packageName, int flags, int userId)
1144       throws NameNotFoundException {
1145     return 0;
1146   }
1147 
1148   /** @see ShadowPackageManager#addPermissionGroupInfo(android.content.pm.PermissionGroupInfo) */
1149   @Implementation
getPermissionGroupInfo(String name, int flags)1150   protected PermissionGroupInfo getPermissionGroupInfo(String name, int flags)
1151       throws NameNotFoundException {
1152     if (extraPermissionGroups.containsKey(name)) {
1153       return new PermissionGroupInfo(extraPermissionGroups.get(name));
1154     }
1155 
1156     for (Package pkg : packages.values()) {
1157       for (PermissionGroup permissionGroup : pkg.permissionGroups) {
1158         if (name.equals(permissionGroup.info.name)) {
1159           return PackageParser.generatePermissionGroupInfo(permissionGroup, flags);
1160         }
1161       }
1162     }
1163 
1164     throw new NameNotFoundException(name);
1165   }
1166 
1167   /** @see ShadowPackageManager#addPermissionGroupInfo(android.content.pm.PermissionGroupInfo) */
1168   @Implementation
getAllPermissionGroups(int flags)1169   protected List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1170     ArrayList<PermissionGroupInfo> allPermissionGroups = new ArrayList<PermissionGroupInfo>();
1171     // To be consistent with Android's implementation, return at most one PermissionGroupInfo object
1172     // per permission group string
1173     HashSet<String> handledPermissionGroups = new HashSet<>();
1174 
1175     for (PermissionGroupInfo permissionGroupInfo : extraPermissionGroups.values()) {
1176       allPermissionGroups.add(new PermissionGroupInfo(permissionGroupInfo));
1177       handledPermissionGroups.add(permissionGroupInfo.name);
1178     }
1179 
1180     for (Package pkg : packages.values()) {
1181       for (PermissionGroup permissionGroup : pkg.permissionGroups) {
1182         if (!handledPermissionGroups.contains(permissionGroup.info.name)) {
1183           PermissionGroupInfo permissionGroupInfo =
1184               PackageParser.generatePermissionGroupInfo(permissionGroup, flags);
1185           allPermissionGroups.add(new PermissionGroupInfo(permissionGroupInfo));
1186           handledPermissionGroups.add(permissionGroup.info.name);
1187         }
1188       }
1189     }
1190 
1191     return allPermissionGroups;
1192   }
1193 
1194   @Implementation
getApplicationInfo(String packageName, int flags)1195   protected ApplicationInfo getApplicationInfo(String packageName, int flags)
1196       throws NameNotFoundException {
1197     PackageInfo info = packageInfos.get(packageName);
1198     if (info != null) {
1199       try {
1200         getPackageInfo(packageName, -1);
1201       } catch (NameNotFoundException e) {
1202         throw new IllegalArgumentException(e);
1203       }
1204 
1205       if (applicationEnabledSettingMap.get(packageName) == COMPONENT_ENABLED_STATE_DISABLED
1206           && (flags & MATCH_UNINSTALLED_PACKAGES) != MATCH_UNINSTALLED_PACKAGES
1207           && (flags & MATCH_DISABLED_COMPONENTS) != MATCH_DISABLED_COMPONENTS) {
1208         throw new NameNotFoundException("Package is disabled, can't find");
1209       }
1210 
1211       if (hiddenPackages.contains(packageName) && !isFlagSet(flags, MATCH_UNINSTALLED_PACKAGES)) {
1212         throw new NameNotFoundException("Package is hidden, can't find");
1213       }
1214 
1215       if (info.applicationInfo != null) {
1216         return new ApplicationInfo(info.applicationInfo);
1217       }
1218     }
1219     throw new NameNotFoundException(packageName);
1220   }
1221 
1222   @Implementation
getApplicationInfoAsUser( String packageName, int flags, UserHandle userId)1223   protected ApplicationInfo getApplicationInfoAsUser(
1224           String packageName, int flags, UserHandle userId) throws NameNotFoundException {
1225     // Currently does not use the user ID.
1226     return getApplicationInfo(packageName, flags);
1227   }
1228 
1229   /**
1230    * Returns all the values added via {@link
1231    * ShadowPackageManager#addSystemSharedLibraryName(String)}.
1232    */
1233   @Implementation
getSystemSharedLibraryNames()1234   protected String[] getSystemSharedLibraryNames() {
1235     return systemSharedLibraryNames.toArray(new String[systemSharedLibraryNames.size()]);
1236   }
1237 
1238   @Implementation(minSdk = N)
getServicesSystemSharedLibraryPackageName()1239   protected @NonNull String getServicesSystemSharedLibraryPackageName() {
1240     return null;
1241   }
1242 
1243   @Implementation(minSdk = N)
getSharedSystemSharedLibraryPackageName()1244   protected @NonNull String getSharedSystemSharedLibraryPackageName() {
1245     return "";
1246   }
1247 
1248   @Implementation(minSdk = N)
hasSystemFeature(String name, int version)1249   protected boolean hasSystemFeature(String name, int version) {
1250     return false;
1251   }
1252 
1253   @Implementation(minSdk = M)
isPermissionRevokedByPolicy(String permName, String pkgName)1254   protected boolean isPermissionRevokedByPolicy(String permName, String pkgName) {
1255     return false;
1256   }
1257 
1258   @Implementation
addPermission(PermissionInfo info)1259   protected boolean addPermission(PermissionInfo info) {
1260     return false;
1261   }
1262 
1263   @Implementation
addPermissionAsync(PermissionInfo info)1264   protected boolean addPermissionAsync(PermissionInfo info) {
1265     return false;
1266   }
1267 
1268   @Implementation
removePermission(String name)1269   protected void removePermission(String name) {}
1270 
1271   @Implementation(minSdk = M)
grantRuntimePermission( String packageName, String permissionName, UserHandle user)1272   protected void grantRuntimePermission(
1273       String packageName, String permissionName, UserHandle user) {
1274 
1275     if (!packageInfos.containsKey(packageName)) {
1276       throw new SecurityException("Package not found: " + packageName);
1277     }
1278     PackageInfo packageInfo = packageInfos.get(packageName);
1279     checkPermissionGrantStateInitialized(packageInfo);
1280 
1281     int permissionIndex = getPermissionIndex(packageInfo, permissionName);
1282     if (permissionIndex < 0) {
1283       throw new SecurityException(
1284           "Permission " + permissionName + " not requested by package " + packageName);
1285     }
1286 
1287     packageInfo.requestedPermissionsFlags[permissionIndex] |= REQUESTED_PERMISSION_GRANTED;
1288   }
1289 
1290   @Implementation(minSdk = M)
revokeRuntimePermission( String packageName, String permissionName, UserHandle user)1291   protected void revokeRuntimePermission(
1292       String packageName, String permissionName, UserHandle user) {
1293 
1294     if (!packageInfos.containsKey(packageName)) {
1295       throw new SecurityException("Package not found: " + packageName);
1296     }
1297     PackageInfo packageInfo = packageInfos.get(packageName);
1298     checkPermissionGrantStateInitialized(packageInfo);
1299 
1300     int permissionIndex = getPermissionIndex(packageInfo, permissionName);
1301     if (permissionIndex < 0) {
1302       throw new SecurityException(
1303           "Permission " + permissionName + " not requested by package " + packageName);
1304     }
1305 
1306     packageInfo.requestedPermissionsFlags[permissionIndex] &= ~REQUESTED_PERMISSION_GRANTED;
1307   }
1308 
checkPermissionGrantStateInitialized(PackageInfo packageInfo)1309   private void checkPermissionGrantStateInitialized(PackageInfo packageInfo) {
1310     if (packageInfo.requestedPermissionsFlags == null) {
1311       // In the real OS this would never be null, but tests don't necessarily initialize this
1312       // structure.
1313       throw new SecurityException(
1314           "Permission grant state (PackageInfo.requestedPermissionFlags) "
1315               + "is null. This operation requires this variable to be initialized.");
1316     }
1317   }
1318 
1319   /**
1320    * Returns the index of the given permission in the PackageInfo.requestedPermissions array, or -1
1321    * if it's not found.
1322    */
getPermissionIndex(PackageInfo packageInfo, String permissionName)1323   private int getPermissionIndex(PackageInfo packageInfo, String permissionName) {
1324     if (packageInfo.requestedPermissions != null) {
1325       for (int i = 0; i < packageInfo.requestedPermissions.length; i++) {
1326         if (permissionName.equals(packageInfo.requestedPermissions[i])) {
1327           return i;
1328         }
1329       }
1330     }
1331 
1332     return -1;
1333   }
1334 
1335   @Implementation(minSdk = M)
getPermissionFlags(String permissionName, String packageName, UserHandle user)1336   protected int getPermissionFlags(String permissionName, String packageName, UserHandle user) {
1337     return 0;
1338   }
1339 
1340   @Implementation(minSdk = M)
updatePermissionFlags( String permissionName, String packageName, int flagMask, int flagValues, UserHandle user)1341   protected void updatePermissionFlags(
1342       String permissionName, String packageName, int flagMask, int flagValues, UserHandle user) {}
1343 
1344   @Implementation
getUidForSharedUser(String sharedUserName)1345   protected int getUidForSharedUser(String sharedUserName) throws NameNotFoundException {
1346     return 0;
1347   }
1348 
1349   @Implementation(minSdk = N)
getInstalledPackagesAsUser(int flags, int userId)1350   protected List<PackageInfo> getInstalledPackagesAsUser(int flags, int userId) {
1351     List<PackageInfo> packages = new ArrayList<>();
1352     for (String packageName : packagesForUserId.getOrDefault(userId, new ArrayList<>())) {
1353       packages.add(packageInfos.get(packageName));
1354     }
1355     return packages;
1356   }
1357 
1358   @Implementation(minSdk = JELLY_BEAN_MR2)
getPackagesHoldingPermissions(String[] permissions, int flags)1359   protected List<PackageInfo> getPackagesHoldingPermissions(String[] permissions, int flags) {
1360     return null;
1361   }
1362 
1363   /** Behaves as {@link #resolveActivity(Intent, int)} and currently ignores userId. */
1364   @Implementation(minSdk = JELLY_BEAN_MR1)
resolveActivityAsUser(Intent intent, int flags, int userId)1365   protected ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) {
1366     return resolveActivity(intent, flags);
1367   }
1368 
1369   @Implementation
queryIntentActivityOptions( ComponentName caller, Intent[] specifics, Intent intent, int flags)1370   protected List<ResolveInfo> queryIntentActivityOptions(
1371       ComponentName caller, Intent[] specifics, Intent intent, int flags) {
1372     return null;
1373   }
1374 
1375   @Implementation(minSdk = N)
queryBroadcastReceiversAsUser(Intent intent, int flags, int userId)1376   protected List<ResolveInfo> queryBroadcastReceiversAsUser(Intent intent, int flags, int userId) {
1377     return null;
1378   }
1379 
1380   @Implementation
queryContentProviders(String processName, int uid, int flags)1381   protected List<ProviderInfo> queryContentProviders(String processName, int uid, int flags) {
1382     return null;
1383   }
1384 
1385   @Implementation
getInstrumentationInfo(ComponentName className, int flags)1386   protected InstrumentationInfo getInstrumentationInfo(ComponentName className, int flags)
1387       throws NameNotFoundException {
1388     return null;
1389   }
1390 
1391   @Implementation
queryInstrumentation(String targetPackage, int flags)1392   protected List<InstrumentationInfo> queryInstrumentation(String targetPackage, int flags) {
1393     return null;
1394   }
1395 
1396   @Nullable
1397   @Implementation
getDrawable( String packageName, @DrawableRes int resId, @Nullable ApplicationInfo appInfo)1398   protected Drawable getDrawable(
1399       String packageName, @DrawableRes int resId, @Nullable ApplicationInfo appInfo) {
1400     Drawable result = drawables.get(new Pair<>(packageName, resId));
1401     if (result != null) {
1402       return result;
1403     }
1404     return Shadow.directlyOn(realObject, ApplicationPackageManager.class)
1405         .getDrawable(packageName, resId, appInfo);
1406   }
1407 
1408   @Implementation
getActivityIcon(ComponentName activityName)1409   protected Drawable getActivityIcon(ComponentName activityName) throws NameNotFoundException {
1410     Drawable result = drawableList.get(activityName);
1411     if (result != null) {
1412       return result;
1413     }
1414     return Shadow.directlyOn(realObject, ApplicationPackageManager.class)
1415         .getActivityIcon(activityName);
1416   }
1417 
1418   @Implementation
getDefaultActivityIcon()1419   protected Drawable getDefaultActivityIcon() {
1420     return Resources.getSystem().getDrawable(com.android.internal.R.drawable.sym_def_app_icon);
1421   }
1422 
1423   @Implementation
getResourcesForActivity(ComponentName activityName)1424   protected Resources getResourcesForActivity(ComponentName activityName)
1425       throws NameNotFoundException {
1426     return getResourcesForApplication(activityName.getPackageName());
1427   }
1428   @Implementation
getResourcesForApplication(String appPackageName)1429   protected Resources getResourcesForApplication(String appPackageName)
1430       throws NameNotFoundException {
1431     if (context.getPackageName().equals(appPackageName)) {
1432       return context.getResources();
1433     } else if (packageInfos.containsKey(appPackageName)) {
1434       Resources appResources = resources.get(appPackageName);
1435       if (appResources == null) {
1436         appResources = new Resources(new AssetManager(), null, null);
1437         resources.put(appPackageName, appResources);
1438       }
1439       return appResources;
1440     }
1441     throw new NameNotFoundException(appPackageName);
1442   }
1443 
1444   @Implementation(minSdk = JELLY_BEAN_MR1)
getResourcesForApplicationAsUser(String appPackageName, int userId)1445   protected Resources getResourcesForApplicationAsUser(String appPackageName, int userId)
1446       throws NameNotFoundException {
1447     return null;
1448   }
1449 
1450   @Implementation(minSdk = M)
addOnPermissionsChangeListener(Object listener)1451   protected void addOnPermissionsChangeListener(Object listener) {}
1452 
1453   @Implementation(minSdk = M)
removeOnPermissionsChangeListener(Object listener)1454   protected void removeOnPermissionsChangeListener(Object listener) {}
1455 
1456   @Implementation(maxSdk = O_MR1)
installPackage( Object packageURI, Object observer, Object flags, Object installerPackageName)1457   protected void installPackage(
1458       Object packageURI, Object observer, Object flags, Object installerPackageName) {}
1459 
1460   @Implementation(minSdk = JELLY_BEAN_MR1)
installExistingPackage(String packageName)1461   protected int installExistingPackage(String packageName) throws NameNotFoundException {
1462     return 0;
1463   }
1464 
1465   @Implementation(minSdk = N)
installExistingPackageAsUser(String packageName, int userId)1466   protected int installExistingPackageAsUser(String packageName, int userId)
1467       throws NameNotFoundException {
1468     return 0;
1469   }
1470 
1471   @Implementation(minSdk = M)
verifyIntentFilter(int id, int verificationCode, List<String> failedDomains)1472   protected void verifyIntentFilter(int id, int verificationCode, List<String> failedDomains) {}
1473 
1474   @Implementation(minSdk = N)
getIntentVerificationStatusAsUser(String packageName, int userId)1475   protected int getIntentVerificationStatusAsUser(String packageName, int userId) {
1476     return 0;
1477   }
1478 
1479   @Implementation(minSdk = N)
updateIntentVerificationStatusAsUser( String packageName, int status, int userId)1480   protected boolean updateIntentVerificationStatusAsUser(
1481       String packageName, int status, int userId) {
1482     return false;
1483   }
1484 
1485   @Implementation(minSdk = M)
getIntentFilterVerifications(String packageName)1486   protected List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName) {
1487     return null;
1488   }
1489 
1490   @Implementation(minSdk = M)
getAllIntentFilters(String packageName)1491   protected List<IntentFilter> getAllIntentFilters(String packageName) {
1492     return null;
1493   }
1494 
1495   @Implementation(minSdk = N)
getDefaultBrowserPackageNameAsUser(int userId)1496   protected String getDefaultBrowserPackageNameAsUser(int userId) {
1497     return null;
1498   }
1499 
1500   @Implementation(minSdk = N)
setDefaultBrowserPackageNameAsUser(String packageName, int userId)1501   protected boolean setDefaultBrowserPackageNameAsUser(String packageName, int userId) {
1502     return false;
1503   }
1504 
1505   @Implementation(minSdk = M)
getMoveStatus(int moveId)1506   protected int getMoveStatus(int moveId) {
1507     return 0;
1508   }
1509 
1510   @Implementation(minSdk = M)
registerMoveCallback(Object callback, Object handler)1511   protected void registerMoveCallback(Object callback, Object handler) {}
1512 
1513   @Implementation(minSdk = M)
unregisterMoveCallback(Object callback)1514   protected void unregisterMoveCallback(Object callback) {}
1515 
1516   @Implementation(minSdk = M)
movePackage(Object packageName, Object vol)1517   protected Object movePackage(Object packageName, Object vol) {
1518     return 0;
1519   }
1520 
1521   @Implementation(minSdk = M)
getPackageCurrentVolume(Object app)1522   protected Object getPackageCurrentVolume(Object app) {
1523     return null;
1524   }
1525 
1526   @Implementation(minSdk = M)
getPackageCandidateVolumes(ApplicationInfo app)1527   protected List<VolumeInfo> getPackageCandidateVolumes(ApplicationInfo app) {
1528     return null;
1529   }
1530 
1531   @Implementation(minSdk = M)
movePrimaryStorage(Object vol)1532   protected Object movePrimaryStorage(Object vol) {
1533     return 0;
1534   }
1535 
1536   @Implementation(minSdk = M)
getPrimaryStorageCurrentVolume()1537   protected @Nullable Object getPrimaryStorageCurrentVolume() {
1538     return null;
1539   }
1540 
1541   @Implementation(minSdk = M)
getPrimaryStorageCandidateVolumes()1542   protected @NonNull List<VolumeInfo> getPrimaryStorageCandidateVolumes() {
1543     return null;
1544   }
1545 
1546   @Implementation(minSdk = N)
deletePackageAsUser( String packageName, IPackageDeleteObserver observer, int flags, int userId)1547   protected void deletePackageAsUser(
1548       String packageName, IPackageDeleteObserver observer, int flags, int userId) {}
1549 
1550   @Implementation
clearApplicationUserData(String packageName, IPackageDataObserver observer)1551   protected void clearApplicationUserData(String packageName, IPackageDataObserver observer) {}
1552 
1553   @Implementation
deleteApplicationCacheFiles(String packageName, IPackageDataObserver observer)1554   protected void deleteApplicationCacheFiles(String packageName, IPackageDataObserver observer) {}
1555 
1556   @Implementation(minSdk = N)
deleteApplicationCacheFilesAsUser( String packageName, int userId, IPackageDataObserver observer)1557   protected void deleteApplicationCacheFilesAsUser(
1558       String packageName, int userId, IPackageDataObserver observer) {}
1559 
1560   @Implementation(minSdk = M)
freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi)1561   protected void freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi) {}
1562 
1563   @Implementation(minSdk = N, maxSdk = O_MR1)
setPackagesSuspendedAsUser( String[] packageNames, boolean suspended, int userId)1564   protected String[] setPackagesSuspendedAsUser(
1565       String[] packageNames, boolean suspended, int userId) {
1566     return null;
1567   }
1568 
1569   @Implementation(minSdk = N)
isPackageSuspendedForUser(String packageName, int userId)1570   protected boolean isPackageSuspendedForUser(String packageName, int userId) {
1571     return false;
1572   }
1573 
1574   @Implementation
addPackageToPreferred(String packageName)1575   protected void addPackageToPreferred(String packageName) {}
1576 
1577   @Implementation
removePackageFromPreferred(String packageName)1578   protected void removePackageFromPreferred(String packageName) {}
1579 
1580   @Implementation
getPreferredPackages(int flags)1581   protected List<PackageInfo> getPreferredPackages(int flags) {
1582     return null;
1583   }
1584 
1585   @Implementation
addPreferredActivity( IntentFilter filter, int match, ComponentName[] set, ComponentName activity)1586   public void addPreferredActivity(
1587       IntentFilter filter, int match, ComponentName[] set, ComponentName activity) {
1588     preferredActivities.put(new IntentFilterWrapper(filter), activity);
1589   }
1590 
1591   @Implementation
replacePreferredActivity( IntentFilter filter, int match, ComponentName[] set, ComponentName activity)1592   protected void replacePreferredActivity(
1593       IntentFilter filter, int match, ComponentName[] set, ComponentName activity) {
1594     addPreferredActivity(filter, match, set, activity);
1595   }
1596 
1597   @Implementation
getPreferredActivities( List<IntentFilter> outFilters, List<ComponentName> outActivities, String packageName)1598   public int getPreferredActivities(
1599       List<IntentFilter> outFilters, List<ComponentName> outActivities, String packageName) {
1600     if (outFilters == null) {
1601       return 0;
1602     }
1603 
1604     Set<IntentFilterWrapper> filters = preferredActivities.keySet();
1605     for (IntentFilter filter : outFilters) {
1606       step:
1607       for (IntentFilterWrapper testFilterWrapper : filters) {
1608         ComponentName name = preferredActivities.get(testFilterWrapper);
1609         IntentFilter testFilter = testFilterWrapper.getFilter();
1610         // filter out based on the given packageName;
1611         if (packageName != null && !name.getPackageName().equals(packageName)) {
1612           continue step;
1613         }
1614 
1615         // Check actions
1616         Iterator<String> iterator = filter.actionsIterator();
1617         while (iterator.hasNext()) {
1618           if (!testFilter.matchAction(iterator.next())) {
1619             continue step;
1620           }
1621         }
1622 
1623         iterator = filter.categoriesIterator();
1624         while (iterator.hasNext()) {
1625           if (!filter.hasCategory(iterator.next())) {
1626             continue step;
1627           }
1628         }
1629 
1630         if (outActivities == null) {
1631           outActivities = new ArrayList<>();
1632         }
1633 
1634         outActivities.add(name);
1635       }
1636     }
1637 
1638     return 0;
1639   }
1640 
1641   @Implementation
clearPackagePreferredActivities(String packageName)1642   protected void clearPackagePreferredActivities(String packageName) {
1643     Iterator<ComponentName> entryIterator = preferredActivities.values().iterator();
1644     while (entryIterator.hasNext()) {
1645       ComponentName next = entryIterator.next();
1646       if (next.getPackageName().equals(packageName)) {
1647         entryIterator.remove();
1648       }
1649     }
1650   }
1651 
1652   @Implementation(minSdk = KITKAT)
getHomeActivities(List<ResolveInfo> outActivities)1653   protected ComponentName getHomeActivities(List<ResolveInfo> outActivities) {
1654     return null;
1655   }
1656 
1657   @Implementation(minSdk = N)
flushPackageRestrictionsAsUser(int userId)1658   protected void flushPackageRestrictionsAsUser(int userId) {}
1659 
1660   @Implementation(minSdk = LOLLIPOP)
setApplicationHiddenSettingAsUser( String packageName, boolean hidden, UserHandle user)1661   protected boolean setApplicationHiddenSettingAsUser(
1662       String packageName, boolean hidden, UserHandle user) {
1663     // Note that this ignores the UserHandle parameter
1664     if (!packageInfos.containsKey(packageName)) {
1665       // Package doesn't exist
1666       return false;
1667     }
1668     if (hidden) {
1669       hiddenPackages.add(packageName);
1670     } else {
1671       hiddenPackages.remove(packageName);
1672     }
1673     return true;
1674   }
1675 
1676   @Implementation(minSdk = LOLLIPOP)
getApplicationHiddenSettingAsUser(String packageName, UserHandle user)1677   protected boolean getApplicationHiddenSettingAsUser(String packageName, UserHandle user) {
1678     // Note that this ignores the UserHandle parameter
1679     if (!packageInfos.containsKey(packageName)) {
1680       // Match Android behaviour of returning true if package isn't found
1681       return true;
1682     }
1683     return hiddenPackages.contains(packageName);
1684   }
1685 
1686   @Implementation(minSdk = LOLLIPOP)
getKeySetByAlias(String packageName, String alias)1687   protected Object getKeySetByAlias(String packageName, String alias) {
1688     return null;
1689   }
1690 
1691   @Implementation(minSdk = LOLLIPOP)
getSigningKeySet(String packageName)1692   protected Object getSigningKeySet(String packageName) {
1693     return null;
1694   }
1695 
1696   @Implementation(minSdk = LOLLIPOP)
isSignedBy(String packageName, Object ks)1697   protected boolean isSignedBy(String packageName, Object ks) {
1698     return false;
1699   }
1700 
1701   @Implementation(minSdk = LOLLIPOP)
isSignedByExactly(String packageName, Object ks)1702   protected boolean isSignedByExactly(String packageName, Object ks) {
1703     return false;
1704   }
1705 
1706   @Implementation
getVerifierDeviceIdentity()1707   protected VerifierDeviceIdentity getVerifierDeviceIdentity() {
1708     return null;
1709   }
1710 
1711   @Implementation(minSdk = LOLLIPOP_MR1)
isUpgrade()1712   protected boolean isUpgrade() {
1713     return false;
1714   }
1715 
1716   @Implementation(minSdk = LOLLIPOP)
isPackageAvailable(String packageName)1717   protected boolean isPackageAvailable(String packageName) {
1718     return false;
1719   }
1720 
1721   @Implementation(minSdk = LOLLIPOP)
addCrossProfileIntentFilter( IntentFilter filter, int sourceUserId, int targetUserId, int flags)1722   protected void addCrossProfileIntentFilter(
1723       IntentFilter filter, int sourceUserId, int targetUserId, int flags) {}
1724 
1725   @Implementation(minSdk = LOLLIPOP)
clearCrossProfileIntentFilters(int sourceUserId)1726   protected void clearCrossProfileIntentFilters(int sourceUserId) {}
1727 
1728   /**
1729    * Gets the unbadged icon based on the values set by {@link
1730    * ShadowPackageManager#setUnbadgedApplicationIcon} or returns null if nothing has been set.
1731    */
1732   @Implementation(minSdk = LOLLIPOP_MR1)
loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo)1733   protected Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) {
1734     Drawable result = unbadgedApplicationIcons.get(itemInfo.packageName);
1735     if (result != null) {
1736       return result;
1737     }
1738     return Shadow.directlyOn(realObject, ApplicationPackageManager.class)
1739         .loadUnbadgedItemIcon(itemInfo, appInfo);
1740   }
1741 
1742   /**
1743    * Adds a profile badge to the icon.
1744    *
1745    * <p>This implementation just returns the unbadged icon, as some default implementations add an
1746    * internal resource to the icon that is unavailable to Robolectric.
1747    */
1748   @Implementation(minSdk = LOLLIPOP)
getUserBadgedIcon(Drawable icon, UserHandle user)1749   protected Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
1750     return icon;
1751   }
1752 
1753   @Implementation(minSdk = O)
canRequestPackageInstalls()1754   protected boolean canRequestPackageInstalls() {
1755     return canRequestPackageInstalls;
1756   }
1757 
1758   @Implementation(minSdk = O)
getChangedPackages(int sequenceNumber)1759   protected Object getChangedPackages(int sequenceNumber) {
1760     if (sequenceNumber < 0 || sequenceNumberChangedPackagesMap.get(sequenceNumber).isEmpty()) {
1761       return null;
1762     }
1763     return new ChangedPackages(
1764         sequenceNumber + 1, new ArrayList<>(sequenceNumberChangedPackagesMap.get(sequenceNumber)));
1765   }
1766 
1767   @Implementation(minSdk = P)
getSystemTextClassifierPackageName()1768   public String getSystemTextClassifierPackageName() {
1769     return "";
1770   }
1771 
1772   @Implementation(minSdk = P)
1773   @HiddenApi
setPackagesSuspended( String[] packageNames, boolean suspended, PersistableBundle appExtras, PersistableBundle launcherExtras, String dialogMessage)1774   protected String[] setPackagesSuspended(
1775       String[] packageNames,
1776       boolean suspended,
1777       PersistableBundle appExtras,
1778       PersistableBundle launcherExtras,
1779       String dialogMessage) {
1780     if (hasProfileOwnerOrDeviceOwnerOnCurrentUser()) {
1781       throw new UnsupportedOperationException();
1782     }
1783     ArrayList<String> unupdatedPackages = new ArrayList<>();
1784     for (String packageName : packageNames) {
1785       if (!canSuspendPackage(packageName)) {
1786         unupdatedPackages.add(packageName);
1787         continue;
1788       }
1789       PackageSetting setting = packageSettings.get(packageName);
1790       if (setting == null) {
1791         unupdatedPackages.add(packageName);
1792         continue;
1793       }
1794       setting.setSuspended(suspended, dialogMessage, appExtras, launcherExtras);
1795     }
1796     return unupdatedPackages.toArray(new String[0]);
1797   }
1798 
1799   /** Returns whether the current user profile has a profile owner or a device owner. */
hasProfileOwnerOrDeviceOwnerOnCurrentUser()1800   private boolean hasProfileOwnerOrDeviceOwnerOnCurrentUser() {
1801     DevicePolicyManager devicePolicyManager =
1802         (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
1803     return devicePolicyManager.getProfileOwner() != null
1804         || (UserHandle.of(UserHandle.myUserId()).isSystem()
1805             && devicePolicyManager.getDeviceOwner() != null);
1806   }
1807 
canSuspendPackage(String packageName)1808   private boolean canSuspendPackage(String packageName) {
1809     // This code approximately mirrors PackageManagerService#canSuspendPackageForUserLocked.
1810     return !packageName.equals(context.getPackageName())
1811         && !isPackageDeviceAdmin(packageName)
1812         && !isPackageActiveLauncher(packageName)
1813         && !isPackageRequiredInstaller(packageName)
1814         && !isPackageRequiredUninstaller(packageName)
1815         && !isPackageRequiredVerifier(packageName)
1816         && !isPackageDefaultDialer(packageName)
1817         && !packageName.equals(PLATFORM_PACKAGE_NAME);
1818   }
1819 
isPackageDeviceAdmin(String packageName)1820   private boolean isPackageDeviceAdmin(String packageName) {
1821     DevicePolicyManager devicePolicyManager =
1822         (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
1823     // Strictly speaking, this should be devicePolicyManager.getDeviceOwnerComponentOnAnyUser(),
1824     // but that method is currently not shadowed.
1825     return packageName.equals(devicePolicyManager.getDeviceOwner());
1826   }
1827 
isPackageActiveLauncher(String packageName)1828   private boolean isPackageActiveLauncher(String packageName) {
1829     Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME);
1830     ResolveInfo info = resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
1831     return info != null && packageName.equals(info.activityInfo.packageName);
1832   }
1833 
isPackageRequiredInstaller(String packageName)1834   private boolean isPackageRequiredInstaller(String packageName) {
1835     Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
1836     intent.addCategory(Intent.CATEGORY_DEFAULT);
1837     intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
1838     ResolveInfo info =
1839         resolveActivity(
1840             intent,
1841             PackageManager.MATCH_SYSTEM_ONLY
1842                 | PackageManager.MATCH_DIRECT_BOOT_AWARE
1843                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
1844     return info != null && packageName.equals(info.activityInfo.packageName);
1845   }
1846 
isPackageRequiredUninstaller(String packageName)1847   private boolean isPackageRequiredUninstaller(String packageName) {
1848     final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
1849     intent.addCategory(Intent.CATEGORY_DEFAULT);
1850     intent.setData(Uri.fromParts(PACKAGE_SCHEME, "foo.bar", null));
1851     ResolveInfo info =
1852         resolveActivity(
1853             intent,
1854             PackageManager.MATCH_SYSTEM_ONLY
1855                 | PackageManager.MATCH_DIRECT_BOOT_AWARE
1856                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
1857     return info != null && packageName.equals(info.activityInfo.packageName);
1858   }
1859 
isPackageRequiredVerifier(String packageName)1860   private boolean isPackageRequiredVerifier(String packageName) {
1861     final Intent intent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
1862     List<ResolveInfo> infos =
1863         queryBroadcastReceivers(
1864             intent,
1865             PackageManager.MATCH_SYSTEM_ONLY
1866                 | PackageManager.MATCH_DIRECT_BOOT_AWARE
1867                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
1868     if (infos != null) {
1869       for (ResolveInfo info : infos) {
1870         if (packageName.equals(info.activityInfo.packageName)) {
1871           return true;
1872         }
1873       }
1874     }
1875     return false;
1876   }
1877 
isPackageDefaultDialer(String packageName)1878   private boolean isPackageDefaultDialer(String packageName) {
1879     TelecomManager telecomManager =
1880         (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
1881     return packageName.equals(telecomManager.getDefaultDialerPackage());
1882   }
1883 
1884   @HiddenApi
1885   @Implementation(minSdk = P)
isPackageSuspended(String packageName)1886   protected boolean isPackageSuspended(String packageName) throws NameNotFoundException {
1887     PackageSetting setting = packageSettings.get(packageName);
1888     if (setting == null) {
1889       throw new NameNotFoundException(packageName);
1890     }
1891     return setting.isSuspended();
1892   }
1893 
1894   @Implementation(minSdk = O)
isInstantApp(String packageName)1895   protected boolean isInstantApp(String packageName) {
1896     return false;
1897   }
1898 
1899   @Implementation(minSdk = Q)
getInstalledModules(int flags)1900   protected List<ModuleInfo> getInstalledModules(int flags) {
1901     return new ArrayList<>();
1902   }
1903 }
1904