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