Home | History | Annotate | Download | only in shadows
      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
    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
    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
    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
    193   protected boolean hasSystemFeature(String name) {
    194     return systemFeatureList.containsKey(name) ? systemFeatureList.get(name) : false;
    195   }
    196 
    197   @Implementation
    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
    204   protected @Nullable String getNameForUid(int uid) {
    205     return namesForUid.get(uid);
    206   }
    207 
    208   @Implementation
    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
    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
    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
    256   protected void setComponentEnabledSetting(ComponentName componentName, int newState, int flags) {
    257     componentList.put(componentName, new ComponentState(newState, flags));
    258   }
    259 
    260   @Implementation
    261   protected void setApplicationEnabledSetting(String packageName, int newState, int flags) {
    262     applicationEnabledSettingMap.put(packageName, newState);
    263   }
    264 
    265   @Implementation
    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
    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)
    301   protected ProviderInfo resolveContentProviderAsUser(
    302       String name, int flags, @UserIdInt int userId) {
    303     return null;
    304   }
    305 
    306   @Implementation
    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
    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
    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 
    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 
    423   private static boolean isFlagSet(int flags, int matchFlag) {
    424     return (flags & matchFlag) == matchFlag;
    425   }
    426 
    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)
    436   protected List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) {
    437     return queryIntentServices(intent, flags);
    438   }
    439 
    440   @Implementation
    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)
    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. */
    474   private static boolean isExplicitIntent(Intent intent) {
    475     return getComponentForIntent(intent) != null;
    476   }
    477 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    611   static ResolveInfo buildResolveInfo(Activity activity) {
    612     ResolveInfo resolveInfo = buildResolveInfo(activity.info);
    613     resolveInfo.activityInfo = activity.info;
    614     return resolveInfo;
    615   }
    616 
    617   static ResolveInfo buildResolveInfo(Service service) {
    618     ResolveInfo resolveInfo = buildResolveInfo(service.info);
    619     resolveInfo.serviceInfo = service.info;
    620     return resolveInfo;
    621   }
    622 
    623   static ResolveInfo buildResolveInfo(Provider provider) {
    624     ResolveInfo resolveInfo = buildResolveInfo(provider.info);
    625     resolveInfo.providerInfo = provider.info;
    626     return resolveInfo;
    627   }
    628 
    629   private static ResolveInfo buildResolveInfo(ComponentInfo componentInfo) {
    630     ResolveInfo resolveInfo = new ResolveInfo();
    631     resolveInfo.resolvePackageName = componentInfo.applicationInfo.packageName;
    632     return resolveInfo;
    633   }
    634 
    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 
    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
    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    */
    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
    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
    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 
    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
    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
    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 
    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
    809   protected Resources getResourcesForApplication(@NonNull ApplicationInfo applicationInfo)
    810       throws PackageManager.NameNotFoundException {
    811     return getResourcesForApplication(applicationInfo.packageName);
    812   }
    813 
    814   @Implementation
    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
    825   protected String getInstallerPackageName(String packageName) {
    826     return packageInstallerMap.get(packageName);
    827   }
    828 
    829   @Implementation
    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)
    850   protected boolean shouldShowRequestPermissionRationale(String permission) {
    851     return permissionRationaleMap.containsKey(permission)
    852         ? permissionRationaleMap.get(permission)
    853         : false;
    854   }
    855 
    856   @Implementation
    857   protected FeatureInfo[] getSystemAvailableFeatures() {
    858     return systemAvailableFeatures.isEmpty()
    859         ? null
    860         : systemAvailableFeatures.toArray(new FeatureInfo[systemAvailableFeatures.size()]);
    861   }
    862 
    863   @Implementation
    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)
    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)
    879   protected void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer) {}
    880 
    881   @Implementation(minSdk = M)
    882   protected void freeStorageAndNotify(
    883       String volumeUuid, long freeStorageSize, IPackageDataObserver observer) {}
    884 
    885   @Implementation
    886   protected void setInstallerPackageName(String targetPackage, String installerPackageName) {
    887     packageInstallerMap.put(targetPackage, installerPackageName);
    888   }
    889 
    890   @Implementation(minSdk = KITKAT)
    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)
    918   protected List<ResolveInfo> queryIntentContentProvidersAsUser(
    919       Intent intent, int flags, int userId) {
    920     return Collections.emptyList();
    921   }
    922 
    923   @Implementation(minSdk = M)
    924   protected String getPermissionControllerPackageName() {
    925     return null;
    926   }
    927 
    928   @Implementation(maxSdk = JELLY_BEAN)
    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)
    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)
    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
    974   protected void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
    975     pendingDeleteCallbacks.put(packageName, observer);
    976   }
    977 
    978   @Implementation
    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
    992   protected boolean isSafeMode() {
    993     return false;
    994   }
    995 
    996   @Implementation
    997   protected Drawable getApplicationIcon(String packageName) throws NameNotFoundException {
    998     return applicationIcons.get(packageName);
    999   }
   1000 
   1001   @Implementation
   1002   protected Drawable getApplicationIcon(ApplicationInfo info) {
   1003     return null;
   1004   }
   1005 
   1006   @Implementation(minSdk = LOLLIPOP)
   1007   protected Drawable getUserBadgeForDensity(UserHandle userHandle, int i) {
   1008     return null;
   1009   }
   1010 
   1011   @Implementation
   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
   1023   protected int checkSignatures(int uid1, int uid2) {
   1024     return 0;
   1025   }
   1026 
   1027   @Implementation
   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 
   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
   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)
   1087   protected PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId)
   1088       throws NameNotFoundException {
   1089     return null;
   1090   }
   1091 
   1092   @Implementation
   1093   protected String[] canonicalToCurrentPackageNames(String[] names) {
   1094     return new String[0];
   1095   }
   1096 
   1097   @Implementation
   1098   protected int[] getPackageGids(String packageName) throws NameNotFoundException {
   1099     return new int[0];
   1100   }
   1101 
   1102   @Implementation(minSdk = N)
   1103   protected int[] getPackageGids(String packageName, int flags) throws NameNotFoundException {
   1104     return null;
   1105   }
   1106 
   1107   @Implementation(minSdk = JELLY_BEAN_MR2)
   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)
   1117   protected int getPackageUidAsUser(String packageName, int userId) throws NameNotFoundException {
   1118     return 0;
   1119   }
   1120 
   1121   @Implementation(minSdk = N)
   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
   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
   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
   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
   1206   protected String[] getSystemSharedLibraryNames() {
   1207     return systemSharedLibraryNames.toArray(new String[systemSharedLibraryNames.size()]);
   1208   }
   1209 
   1210   @Implementation(minSdk = N)
   1211   protected @NonNull String getServicesSystemSharedLibraryPackageName() {
   1212     return null;
   1213   }
   1214 
   1215   @Implementation(minSdk = N)
   1216   protected @NonNull String getSharedSystemSharedLibraryPackageName() {
   1217     return "";
   1218   }
   1219 
   1220   @Implementation(minSdk = N)
   1221   protected boolean hasSystemFeature(String name, int version) {
   1222     return false;
   1223   }
   1224 
   1225   @Implementation(minSdk = M)
   1226   protected boolean isPermissionRevokedByPolicy(String permName, String pkgName) {
   1227     return false;
   1228   }
   1229 
   1230   @Implementation
   1231   protected boolean addPermission(PermissionInfo info) {
   1232     return false;
   1233   }
   1234 
   1235   @Implementation
   1236   protected boolean addPermissionAsync(PermissionInfo info) {
   1237     return false;
   1238   }
   1239 
   1240   @Implementation
   1241   protected void removePermission(String name) {}
   1242 
   1243   @Implementation(minSdk = M)
   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)
   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 
   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    */
   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)
   1308   protected int getPermissionFlags(String permissionName, String packageName, UserHandle user) {
   1309     return 0;
   1310   }
   1311 
   1312   @Implementation(minSdk = M)
   1313   protected void updatePermissionFlags(
   1314       String permissionName, String packageName, int flagMask, int flagValues, UserHandle user) {}
   1315 
   1316   @Implementation
   1317   protected int getUidForSharedUser(String sharedUserName) throws NameNotFoundException {
   1318     return 0;
   1319   }
   1320 
   1321   @Implementation(minSdk = N)
   1322   protected List<PackageInfo> getInstalledPackagesAsUser(int flags, int userId) {
   1323     return null;
   1324   }
   1325 
   1326   @Implementation(minSdk = JELLY_BEAN_MR2)
   1327   protected List<PackageInfo> getPackagesHoldingPermissions(String[] permissions, int flags) {
   1328     return null;
   1329   }
   1330 
   1331   @Implementation(minSdk = JELLY_BEAN_MR1)
   1332   protected ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) {
   1333     return null;
   1334   }
   1335 
   1336   @Implementation
   1337   protected List<ResolveInfo> queryIntentActivityOptions(
   1338       ComponentName caller, Intent[] specifics, Intent intent, int flags) {
   1339     return null;
   1340   }
   1341 
   1342   @Implementation(minSdk = N)
   1343   protected List<ResolveInfo> queryBroadcastReceiversAsUser(Intent intent, int flags, int userId) {
   1344     return null;
   1345   }
   1346 
   1347   @Implementation
   1348   protected List<ProviderInfo> queryContentProviders(String processName, int uid, int flags) {
   1349     return null;
   1350   }
   1351 
   1352   @Implementation
   1353   protected InstrumentationInfo getInstrumentationInfo(ComponentName className, int flags)
   1354       throws NameNotFoundException {
   1355     return null;
   1356   }
   1357 
   1358   @Implementation
   1359   protected List<InstrumentationInfo> queryInstrumentation(String targetPackage, int flags) {
   1360     return null;
   1361   }
   1362 
   1363   @Nullable
   1364   @Implementation
   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
   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
   1386   protected Drawable getDefaultActivityIcon() {
   1387     return Resources.getSystem().getDrawable(com.android.internal.R.drawable.sym_def_app_icon);
   1388   }
   1389 
   1390   @Implementation
   1391   protected Resources getResourcesForActivity(ComponentName activityName)
   1392       throws NameNotFoundException {
   1393     return getResourcesForApplication(activityName.getPackageName());
   1394   }
   1395   @Implementation
   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)
   1412   protected Resources getResourcesForApplicationAsUser(String appPackageName, int userId)
   1413       throws NameNotFoundException {
   1414     return null;
   1415   }
   1416 
   1417   @Implementation(minSdk = M)
   1418   protected void addOnPermissionsChangeListener(Object listener) {}
   1419 
   1420   @Implementation(minSdk = M)
   1421   protected void removeOnPermissionsChangeListener(Object listener) {}
   1422 
   1423   @Implementation(maxSdk = O_MR1)
   1424   protected void installPackage(
   1425       Object packageURI, Object observer, Object flags, Object installerPackageName) {}
   1426 
   1427   @Implementation(minSdk = JELLY_BEAN_MR1)
   1428   protected int installExistingPackage(String packageName) throws NameNotFoundException {
   1429     return 0;
   1430   }
   1431 
   1432   @Implementation(minSdk = N)
   1433   protected int installExistingPackageAsUser(String packageName, int userId)
   1434       throws NameNotFoundException {
   1435     return 0;
   1436   }
   1437 
   1438   @Implementation(minSdk = M)
   1439   protected void verifyIntentFilter(int id, int verificationCode, List<String> failedDomains) {}
   1440 
   1441   @Implementation(minSdk = N)
   1442   protected int getIntentVerificationStatusAsUser(String packageName, int userId) {
   1443     return 0;
   1444   }
   1445 
   1446   @Implementation(minSdk = N)
   1447   protected boolean updateIntentVerificationStatusAsUser(
   1448       String packageName, int status, int userId) {
   1449     return false;
   1450   }
   1451 
   1452   @Implementation(minSdk = M)
   1453   protected List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName) {
   1454     return null;
   1455   }
   1456 
   1457   @Implementation(minSdk = M)
   1458   protected List<IntentFilter> getAllIntentFilters(String packageName) {
   1459     return null;
   1460   }
   1461 
   1462   @Implementation(minSdk = N)
   1463   protected String getDefaultBrowserPackageNameAsUser(int userId) {
   1464     return null;
   1465   }
   1466 
   1467   @Implementation(minSdk = N)
   1468   protected boolean setDefaultBrowserPackageNameAsUser(String packageName, int userId) {
   1469     return false;
   1470   }
   1471 
   1472   @Implementation(minSdk = M)
   1473   protected int getMoveStatus(int moveId) {
   1474     return 0;
   1475   }
   1476 
   1477   @Implementation(minSdk = M)
   1478   protected void registerMoveCallback(Object callback, Object handler) {}
   1479 
   1480   @Implementation(minSdk = M)
   1481   protected void unregisterMoveCallback(Object callback) {}
   1482 
   1483   @Implementation(minSdk = M)
   1484   protected Object movePackage(Object packageName, Object vol) {
   1485     return 0;
   1486   }
   1487 
   1488   @Implementation(minSdk = M)
   1489   protected Object getPackageCurrentVolume(Object app) {
   1490     return null;
   1491   }
   1492 
   1493   @Implementation(minSdk = M)
   1494   protected List<VolumeInfo> getPackageCandidateVolumes(ApplicationInfo app) {
   1495     return null;
   1496   }
   1497 
   1498   @Implementation(minSdk = M)
   1499   protected Object movePrimaryStorage(Object vol) {
   1500     return 0;
   1501   }
   1502 
   1503   @Implementation(minSdk = M)
   1504   protected @Nullable Object getPrimaryStorageCurrentVolume() {
   1505     return null;
   1506   }
   1507 
   1508   @Implementation(minSdk = M)
   1509   protected @NonNull List<VolumeInfo> getPrimaryStorageCandidateVolumes() {
   1510     return null;
   1511   }
   1512 
   1513   @Implementation(minSdk = N)
   1514   protected void deletePackageAsUser(
   1515       String packageName, IPackageDeleteObserver observer, int flags, int userId) {}
   1516 
   1517   @Implementation
   1518   protected void clearApplicationUserData(String packageName, IPackageDataObserver observer) {}
   1519 
   1520   @Implementation
   1521   protected void deleteApplicationCacheFiles(String packageName, IPackageDataObserver observer) {}
   1522 
   1523   @Implementation(minSdk = N)
   1524   protected void deleteApplicationCacheFilesAsUser(
   1525       String packageName, int userId, IPackageDataObserver observer) {}
   1526 
   1527   @Implementation(minSdk = M)
   1528   protected void freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi) {}
   1529 
   1530   @Implementation(minSdk = N, maxSdk = O_MR1)
   1531   protected String[] setPackagesSuspendedAsUser(
   1532       String[] packageNames, boolean suspended, int userId) {
   1533     return null;
   1534   }
   1535 
   1536   @Implementation(minSdk = N)
   1537   protected boolean isPackageSuspendedForUser(String packageName, int userId) {
   1538     return false;
   1539   }
   1540 
   1541   @Implementation
   1542   protected void addPackageToPreferred(String packageName) {}
   1543 
   1544   @Implementation
   1545   protected void removePackageFromPreferred(String packageName) {}
   1546 
   1547   @Implementation
   1548   protected List<PackageInfo> getPreferredPackages(int flags) {
   1549     return null;
   1550   }
   1551 
   1552   @Implementation
   1553   public void addPreferredActivity(
   1554       IntentFilter filter, int match, ComponentName[] set, ComponentName activity) {
   1555     preferredActivities.put(new IntentFilterWrapper(filter), activity);
   1556   }
   1557 
   1558   @Implementation
   1559   protected void replacePreferredActivity(
   1560       IntentFilter filter, int match, ComponentName[] set, ComponentName activity) {
   1561     addPreferredActivity(filter, match, set, activity);
   1562   }
   1563 
   1564   @Implementation
   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
   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)
   1620   protected ComponentName getHomeActivities(List<ResolveInfo> outActivities) {
   1621     return null;
   1622   }
   1623 
   1624   @Implementation(minSdk = N)
   1625   protected void flushPackageRestrictionsAsUser(int userId) {}
   1626 
   1627   @Implementation(minSdk = LOLLIPOP)
   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)
   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)
   1654   protected Object getKeySetByAlias(String packageName, String alias) {
   1655     return null;
   1656   }
   1657 
   1658   @Implementation(minSdk = LOLLIPOP)
   1659   protected Object getSigningKeySet(String packageName) {
   1660     return null;
   1661   }
   1662 
   1663   @Implementation(minSdk = LOLLIPOP)
   1664   protected boolean isSignedBy(String packageName, Object ks) {
   1665     return false;
   1666   }
   1667 
   1668   @Implementation(minSdk = LOLLIPOP)
   1669   protected boolean isSignedByExactly(String packageName, Object ks) {
   1670     return false;
   1671   }
   1672 
   1673   @Implementation
   1674   protected VerifierDeviceIdentity getVerifierDeviceIdentity() {
   1675     return null;
   1676   }
   1677 
   1678   @Implementation(minSdk = LOLLIPOP_MR1)
   1679   protected boolean isUpgrade() {
   1680     return false;
   1681   }
   1682 
   1683   @Implementation(minSdk = LOLLIPOP)
   1684   protected boolean isPackageAvailable(String packageName) {
   1685     return false;
   1686   }
   1687 
   1688   @Implementation(minSdk = LOLLIPOP)
   1689   protected void addCrossProfileIntentFilter(
   1690       IntentFilter filter, int sourceUserId, int targetUserId, int flags) {}
   1691 
   1692   @Implementation(minSdk = LOLLIPOP)
   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)
   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)
   1716   protected Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
   1717     return icon;
   1718   }
   1719 
   1720   @Implementation(minSdk = O)
   1721   protected boolean canRequestPackageInstalls() {
   1722     return canRequestPackageInstalls;
   1723   }
   1724 
   1725   @Implementation(minSdk = O)
   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)
   1735   public String getSystemTextClassifierPackageName() {
   1736     return "";
   1737   }
   1738 
   1739   @Implementation(minSdk = P)
   1740   @HiddenApi
   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. */
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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)
   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)
   1862   protected boolean isInstantApp(String packageName) {
   1863     return false;
   1864   }
   1865 
   1866   @Implementation(minSdk = Q)
   1867   protected List<ModuleInfo> getInstalledModules(int flags) {
   1868     return new ArrayList<>();
   1869   }
   1870 }
   1871