Home | History | Annotate | Download | only in shadows
      1 package org.robolectric.shadows;
      2 
      3 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
      4 import static android.content.pm.PackageManager.GET_ACTIVITIES;
      5 import static android.content.pm.PackageManager.GET_CONFIGURATIONS;
      6 import static android.content.pm.PackageManager.GET_GIDS;
      7 import static android.content.pm.PackageManager.GET_INSTRUMENTATION;
      8 import static android.content.pm.PackageManager.GET_INTENT_FILTERS;
      9 import static android.content.pm.PackageManager.GET_META_DATA;
     10 import static android.content.pm.PackageManager.GET_PERMISSIONS;
     11 import static android.content.pm.PackageManager.GET_PROVIDERS;
     12 import static android.content.pm.PackageManager.GET_RECEIVERS;
     13 import static android.content.pm.PackageManager.GET_RESOLVED_FILTER;
     14 import static android.content.pm.PackageManager.GET_SERVICES;
     15 import static android.content.pm.PackageManager.GET_SHARED_LIBRARY_FILES;
     16 import static android.content.pm.PackageManager.GET_SIGNATURES;
     17 import static android.content.pm.PackageManager.GET_URI_PERMISSION_PATTERNS;
     18 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
     19 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
     20 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
     21 import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
     22 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
     23 import static android.content.pm.PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
     24 import static android.content.pm.PackageManager.SIGNATURE_MATCH;
     25 import static android.content.pm.PackageManager.SIGNATURE_NEITHER_SIGNED;
     26 import static android.content.pm.PackageManager.SIGNATURE_NO_MATCH;
     27 import static android.content.pm.PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
     28 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
     29 import static android.os.Build.VERSION_CODES.KITKAT;
     30 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1;
     31 import static android.os.Build.VERSION_CODES.M;
     32 import static android.os.Build.VERSION_CODES.N;
     33 import static java.util.Arrays.asList;
     34 
     35 import android.Manifest;
     36 import android.annotation.Nullable;
     37 import android.annotation.UserIdInt;
     38 import android.content.ComponentName;
     39 import android.content.Context;
     40 import android.content.Intent;
     41 import android.content.IntentFilter;
     42 import android.content.IntentFilter.AuthorityEntry;
     43 import android.content.IntentSender;
     44 import android.content.pm.ApplicationInfo;
     45 import android.content.pm.ComponentInfo;
     46 import android.content.pm.FeatureInfo;
     47 import android.content.pm.IPackageDataObserver;
     48 import android.content.pm.IPackageDeleteObserver;
     49 import android.content.pm.PackageInfo;
     50 import android.content.pm.PackageManager;
     51 import android.content.pm.PackageManager.NameNotFoundException;
     52 import android.content.pm.PackageParser;
     53 import android.content.pm.PackageParser.Component;
     54 import android.content.pm.PackageParser.Package;
     55 import android.content.pm.PackageStats;
     56 import android.content.pm.PackageUserState;
     57 import android.content.pm.PermissionGroupInfo;
     58 import android.content.pm.PermissionInfo;
     59 import android.content.pm.ResolveInfo;
     60 import android.content.pm.Signature;
     61 import android.content.res.Resources;
     62 import android.graphics.drawable.Drawable;
     63 import android.net.Uri;
     64 import android.os.Binder;
     65 import android.os.Build;
     66 import android.os.Build.VERSION;
     67 import android.os.PatternMatcher;
     68 import android.os.PersistableBundle;
     69 import android.os.Process;
     70 import android.os.RemoteException;
     71 import android.os.UserHandle;
     72 import android.util.ArraySet;
     73 import android.util.Pair;
     74 import com.google.common.base.Preconditions;
     75 import com.google.common.collect.HashMultimap;
     76 import com.google.common.collect.Multimap;
     77 import java.util.ArrayList;
     78 import java.util.Arrays;
     79 import java.util.Collections;
     80 import java.util.Comparator;
     81 import java.util.HashMap;
     82 import java.util.HashSet;
     83 import java.util.Iterator;
     84 import java.util.LinkedHashMap;
     85 import java.util.List;
     86 import java.util.Map;
     87 import java.util.Objects;
     88 import java.util.Set;
     89 import java.util.TreeMap;
     90 import org.robolectric.RuntimeEnvironment;
     91 import org.robolectric.annotation.Implementation;
     92 import org.robolectric.annotation.Implements;
     93 import org.robolectric.annotation.Resetter;
     94 import org.robolectric.util.ReflectionHelpers;
     95 import org.robolectric.util.TempDirectory;
     96 
     97 @Implements(PackageManager.class)
     98 public class ShadowPackageManager {
     99 
    100   static Map<String, Boolean> permissionRationaleMap = new HashMap<>();
    101   static List<FeatureInfo> systemAvailableFeatures = new ArrayList<>();
    102   static final List<String> systemSharedLibraryNames = new ArrayList<>();
    103   static final Map<String, PackageInfo> packageInfos = new LinkedHashMap<>();
    104   static final Map<String, Package> packages = new LinkedHashMap<>();
    105   private static Map<String, PackageInfo> packageArchiveInfo = new HashMap<>();
    106   static final Map<String, PackageStats> packageStatsMap = new HashMap<>();
    107   static final Map<String, String> packageInstallerMap = new HashMap<>();
    108   static final Map<Integer, String[]> packagesForUid = new HashMap<>();
    109   static final Map<String, Integer> uidForPackage = new HashMap<>();
    110   static final Map<Integer, String> namesForUid = new HashMap<>();
    111   static final Map<Integer, Integer> verificationResults = new HashMap<>();
    112   static final Map<Integer, Long> verificationTimeoutExtension = new HashMap<>();
    113   static final Map<String, String> currentToCanonicalNames = new HashMap<>();
    114   static final Map<ComponentName, ComponentState> componentList = new LinkedHashMap<>();
    115   static final Map<ComponentName, Drawable> drawableList = new LinkedHashMap<>();
    116   static final Map<String, Drawable> applicationIcons = new HashMap<>();
    117   static final Map<String, Drawable> unbadgedApplicationIcons = new HashMap<>();
    118   static final Map<String, Boolean> systemFeatureList = new LinkedHashMap<>();
    119   static final Map<IntentFilterWrapper, ComponentName> preferredActivities = new LinkedHashMap<>();
    120   static final Map<Pair<String, Integer>, Drawable> drawables = new LinkedHashMap<>();
    121   static final Map<String, Integer> applicationEnabledSettingMap = new HashMap<>();
    122   static Map<String, PermissionInfo> extraPermissions = new HashMap<>();
    123   static Map<String, PermissionGroupInfo> extraPermissionGroups = new HashMap<>();
    124   public static Map<String, Resources> resources = new HashMap<>();
    125   private static final Map<Intent, List<ResolveInfo>> resolveInfoForIntent =
    126       new TreeMap<>(new IntentComparator());
    127   private static Set<String> deletedPackages = new HashSet<>();
    128   static Map<String, IPackageDeleteObserver> pendingDeleteCallbacks = new HashMap<>();
    129   static Set<String> hiddenPackages = new HashSet<>();
    130   static Multimap<Integer, String> sequenceNumberChangedPackagesMap = HashMultimap.create();
    131   static boolean canRequestPackageInstalls = false;
    132 
    133   /**
    134    * Settings for a particular package.
    135    *
    136    * <p>This class mirrors {@link com.android.server.pm.PackageSetting}, which is used by {@link
    137    * PackageManager}.
    138    */
    139   public static class PackageSetting {
    140 
    141     /** Whether the package is suspended in {@link PackageManager}. */
    142     private boolean suspended = false;
    143 
    144     /** The message to be displayed to the user when they try to launch the app. */
    145     private String dialogMessage = null;
    146 
    147     /** An optional {@link PersistableBundle} shared with the app. */
    148     private PersistableBundle suspendedAppExtras = null;
    149 
    150     /** An optional {@link PersistableBundle} shared with the launcher. */
    151     private PersistableBundle suspendedLauncherExtras = null;
    152 
    153     public PackageSetting() {}
    154 
    155     public PackageSetting(PackageSetting that) {
    156       this.suspended = that.suspended;
    157       this.dialogMessage = that.dialogMessage;
    158       this.suspendedAppExtras = deepCopyNullablePersistableBundle(that.suspendedAppExtras);
    159       this.suspendedLauncherExtras =
    160           deepCopyNullablePersistableBundle(that.suspendedLauncherExtras);
    161     }
    162 
    163     /**
    164      * Sets the suspension state of the package.
    165      *
    166      * <p>If {@code suspended} is false, {@code dialogMessage}, {@code appExtras}, and {@code
    167      * launcherExtras} will be ignored.
    168      */
    169     void setSuspended(
    170         boolean suspended,
    171         String dialogMessage,
    172         PersistableBundle appExtras,
    173         PersistableBundle launcherExtras) {
    174       this.suspended = suspended;
    175       this.dialogMessage = suspended ? dialogMessage : null;
    176       this.suspendedAppExtras = suspended ? deepCopyNullablePersistableBundle(appExtras) : null;
    177       this.suspendedLauncherExtras =
    178           suspended ? deepCopyNullablePersistableBundle(launcherExtras) : null;
    179     }
    180 
    181     public boolean isSuspended() {
    182       return suspended;
    183     }
    184 
    185     public String getDialogMessage() {
    186       return dialogMessage;
    187     }
    188 
    189     public PersistableBundle getSuspendedAppExtras() {
    190       return suspendedAppExtras;
    191     }
    192 
    193     public PersistableBundle getSuspendedLauncherExtras() {
    194       return suspendedLauncherExtras;
    195     }
    196 
    197     private static PersistableBundle deepCopyNullablePersistableBundle(PersistableBundle bundle) {
    198       return bundle == null ? null : bundle.deepCopy();
    199     }
    200   }
    201 
    202   static final Map<String, PackageSetting> packageSettings = new HashMap<>();
    203 
    204   // From com.android.server.pm.PackageManagerService.compareSignatures().
    205   static int compareSignature(Signature[] signatures1, Signature[] signatures2) {
    206     if (signatures1 == null) {
    207       return (signatures2 == null) ? SIGNATURE_NEITHER_SIGNED : SIGNATURE_FIRST_NOT_SIGNED;
    208     }
    209     if (signatures2 == null) {
    210       return SIGNATURE_SECOND_NOT_SIGNED;
    211     }
    212     if (signatures1.length != signatures2.length) {
    213       return SIGNATURE_NO_MATCH;
    214     }
    215     HashSet<Signature> signatures1set = new HashSet<>(asList(signatures1));
    216     HashSet<Signature> signatures2set = new HashSet<>(asList(signatures2));
    217     return signatures1set.equals(signatures2set) ? SIGNATURE_MATCH : SIGNATURE_NO_MATCH;
    218   }
    219 
    220   static String resolvePackageName(String packageName, ComponentName componentName) {
    221     String classString = componentName.getClassName();
    222     int index = classString.indexOf('.');
    223     if (index == -1) {
    224       classString = packageName + "." + classString;
    225     } else if (index == 0) {
    226       classString = packageName + classString;
    227     }
    228     return classString;
    229   }
    230 
    231   // TODO(christianw): reconcile with ParallelUniverse.setUpPackageStorage
    232   private static void setUpPackageStorage(ApplicationInfo applicationInfo) {
    233     TempDirectory tempDirectory = RuntimeEnvironment.getTempDirectory();
    234 
    235     if (applicationInfo.sourceDir == null) {
    236       applicationInfo.sourceDir =
    237           tempDirectory
    238               .createIfNotExists(applicationInfo.packageName + "-sourceDir")
    239               .toAbsolutePath()
    240               .toString();
    241     }
    242 
    243     if (applicationInfo.dataDir == null) {
    244       applicationInfo.dataDir =
    245           tempDirectory
    246               .createIfNotExists(applicationInfo.packageName + "-dataDir")
    247               .toAbsolutePath()
    248               .toString();
    249     }
    250     if (applicationInfo.publicSourceDir == null) {
    251       applicationInfo.publicSourceDir = applicationInfo.sourceDir;
    252     }
    253     if (RuntimeEnvironment.getApiLevel() >= N) {
    254       applicationInfo.credentialProtectedDataDir =
    255           tempDirectory.createIfNotExists("userDataDir").toAbsolutePath().toString();
    256       applicationInfo.deviceProtectedDataDir =
    257           tempDirectory.createIfNotExists("deviceDataDir").toAbsolutePath().toString();
    258     }
    259   }
    260 
    261   /**
    262    * Sets extra resolve infos for an intent.
    263    *
    264    * <p>Those entries are added to whatever might be in the manifest already.
    265    *
    266    * <p>Note that all resolve infos will have {@link ResolveInfo#isDefault} field set to {@code
    267    * true} to allow their resolution for implicit intents. If this is not what you want, then you
    268    * still have the reference to those ResolveInfos, and you can set the field back to {@code
    269    * false}.
    270    */
    271   public void setResolveInfosForIntent(Intent intent, List<ResolveInfo> info) {
    272     resolveInfoForIntent.remove(intent);
    273     for (ResolveInfo resolveInfo : info) {
    274       addResolveInfoForIntent(intent, resolveInfo);
    275     }
    276   }
    277 
    278   /**
    279    * @deprecated please use {@link #setResolveInfosForIntent} or {@link
    280    *     #addResolveInfoForIntent(Intent, ResolveInfo)} instead.
    281    */
    282   @Deprecated
    283   public void addResolveInfoForIntent(Intent intent, List<ResolveInfo> info) {
    284     setResolveInfosForIntent(intent, info);
    285   }
    286 
    287   /**
    288    * Adds extra resolve info for an intent.
    289    *
    290    * <p>Note that this resolve info will have {@link ResolveInfo#isDefault} field set to {@code
    291    * true} to allow its resolution for implicit intents. If this is not what you want, then please
    292    * use {@link #addResolveInfoForIntentNoDefaults} instead.
    293    */
    294   public void addResolveInfoForIntent(Intent intent, ResolveInfo info) {
    295     info.isDefault = true;
    296     ComponentInfo[] componentInfos =
    297         new ComponentInfo[] {
    298           info.activityInfo,
    299           info.serviceInfo,
    300           Build.VERSION.SDK_INT >= KITKAT ? info.providerInfo : null
    301         };
    302     for (ComponentInfo component : componentInfos) {
    303       if (component != null && component.applicationInfo != null) {
    304         component.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
    305       }
    306     }
    307     addResolveInfoForIntentNoDefaults(intent, info);
    308   }
    309 
    310   /**
    311    * Adds the {@code info} as {@link ResolveInfo} for the intent but without applying any default
    312    * values.
    313    *
    314    * <p>In particular it will not make the {@link ResolveInfo#isDefault} field {@code true}, that
    315    * means that this resolve info will not resolve for {@link Intent#resolveActivity} and {@link
    316    * Context#startActivity}.
    317    */
    318   public void addResolveInfoForIntentNoDefaults(Intent intent, ResolveInfo info) {
    319     Preconditions.checkNotNull(info);
    320     List<ResolveInfo> infoList = resolveInfoForIntent.get(intent);
    321     if (infoList == null) {
    322       infoList = new ArrayList<>();
    323       resolveInfoForIntent.put(intent, infoList);
    324     }
    325     infoList.add(info);
    326   }
    327 
    328   public void removeResolveInfosForIntent(Intent intent, String packageName) {
    329     List<ResolveInfo> infoList = resolveInfoForIntent.get(intent);
    330     if (infoList == null) {
    331       infoList = new ArrayList<>();
    332       resolveInfoForIntent.put(intent, infoList);
    333     }
    334 
    335     for (Iterator<ResolveInfo> iterator = infoList.iterator(); iterator.hasNext(); ) {
    336       ResolveInfo resolveInfo = iterator.next();
    337       if (getPackageName(resolveInfo).equals(packageName)) {
    338         iterator.remove();
    339       }
    340     }
    341   }
    342 
    343   private static String getPackageName(ResolveInfo resolveInfo) {
    344     if (resolveInfo.resolvePackageName != null) {
    345       return resolveInfo.resolvePackageName;
    346     } else if (resolveInfo.activityInfo != null) {
    347       return resolveInfo.activityInfo.packageName;
    348     } else if (resolveInfo.serviceInfo != null) {
    349       return resolveInfo.serviceInfo.packageName;
    350     } else if (resolveInfo.providerInfo != null) {
    351       return resolveInfo.providerInfo.packageName;
    352     }
    353     throw new IllegalStateException(
    354         "Could not find package name for ResolveInfo " + resolveInfo.toString());
    355   }
    356 
    357   public void addActivityIcon(ComponentName component, Drawable drawable) {
    358     drawableList.put(component, drawable);
    359   }
    360 
    361   public void addActivityIcon(Intent intent, Drawable drawable) {
    362     drawableList.put(intent.getComponent(), drawable);
    363   }
    364 
    365   public void setApplicationIcon(String packageName, Drawable drawable) {
    366     applicationIcons.put(packageName, drawable);
    367   }
    368 
    369   public void setUnbadgedApplicationIcon(String packageName, Drawable drawable) {
    370     unbadgedApplicationIcons.put(packageName, drawable);
    371   }
    372 
    373   /**
    374    * Return the flags set in call to {@link
    375    * android.app.ApplicationPackageManager#setComponentEnabledSetting(ComponentName, int, int)}.
    376    *
    377    * @param componentName The component name.
    378    * @return The flags.
    379    */
    380   public int getComponentEnabledSettingFlags(ComponentName componentName) {
    381     ComponentState state = componentList.get(componentName);
    382     return state != null ? state.flags : 0;
    383   }
    384 
    385   /**
    386    * Installs a package with the {@link PackageManager}.
    387    *
    388    * <p>In order to create PackageInfo objects in a valid state please use {@link
    389    * androidx.test.core.content.pm.PackageInfoBuilder}.
    390    *
    391    * <p>This method automatically simulates instalation of a package in the system, so it adds a
    392    * flag {@link ApplicationInfo#FLAG_INSTALLED} to the application info and makes sure it exits. It
    393    * will update applicationInfo in package components as well.
    394    *
    395    * <p>If you don't want the package to be installed, use {@link #addPackageNoDefaults} instead.
    396    */
    397   public void installPackage(PackageInfo packageInfo) {
    398     ApplicationInfo appInfo = packageInfo.applicationInfo;
    399     if (appInfo == null) {
    400       appInfo = new ApplicationInfo();
    401       appInfo.packageName = packageInfo.packageName;
    402       packageInfo.applicationInfo = appInfo;
    403     }
    404     appInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
    405     ComponentInfo[][] componentInfoArrays =
    406         new ComponentInfo[][] {
    407           packageInfo.activities,
    408           packageInfo.services,
    409           packageInfo.providers,
    410           packageInfo.receivers,
    411         };
    412     for (ComponentInfo[] componentInfos : componentInfoArrays) {
    413       if (componentInfos == null) {
    414         continue;
    415       }
    416       for (ComponentInfo componentInfo : componentInfos) {
    417         if (componentInfo.applicationInfo == null) {
    418           componentInfo.applicationInfo = appInfo;
    419         }
    420         componentInfo.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
    421       }
    422     }
    423     addPackageNoDefaults(packageInfo);
    424   }
    425 
    426   /**
    427    * Adds a package to the {@link PackageManager}, but doesn't set any default values on it.
    428    *
    429    * <p>Right now it will not set {@link ApplicationInfo#FLAG_INSTALLED} flag on its application, so
    430    * if not set explicitly, it will be treated as not installed.
    431    */
    432   public void addPackageNoDefaults(PackageInfo packageInfo) {
    433     PackageStats packageStats = new PackageStats(packageInfo.packageName);
    434     addPackage(packageInfo, packageStats);
    435   }
    436 
    437   /**
    438    * Installs a package with its stats with the {@link PackageManager}.
    439    *
    440    * <p>This method doesn't add any defaults to the {@code packageInfo} parameters. You should make
    441    * sure it is valid (see {@link #installPackage(PackageInfo)}).
    442    */
    443   public synchronized void addPackage(PackageInfo packageInfo, PackageStats packageStats) {
    444     Preconditions.checkArgument(packageInfo.packageName.equals(packageStats.packageName));
    445 
    446     packageInfos.put(packageInfo.packageName, packageInfo);
    447     packageStatsMap.put(packageInfo.packageName, packageStats);
    448 
    449     packageSettings.put(packageInfo.packageName, new PackageSetting());
    450 
    451     applicationEnabledSettingMap.put(
    452         packageInfo.packageName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
    453     if (packageInfo.applicationInfo != null) {
    454       namesForUid.put(packageInfo.applicationInfo.uid, packageInfo.packageName);
    455     }
    456   }
    457 
    458   /** @deprecated Use {@link #installPackage(PackageInfo)} instead. */
    459   @Deprecated
    460   public void addPackage(String packageName) {
    461     PackageInfo packageInfo = new PackageInfo();
    462     packageInfo.packageName = packageName;
    463 
    464     ApplicationInfo applicationInfo = new ApplicationInfo();
    465 
    466     applicationInfo.packageName = packageName;
    467     // TODO: setUpPackageStorage should be in installPackage but we need to fix all tests first
    468     setUpPackageStorage(applicationInfo);
    469     packageInfo.applicationInfo = applicationInfo;
    470     installPackage(packageInfo);
    471   }
    472 
    473   /** This method is getting renamed to {link {@link #installPackage}. */
    474   @Deprecated
    475   public void addPackage(PackageInfo packageInfo) {
    476     installPackage(packageInfo);
    477   }
    478 
    479   /**
    480    * Testing API allowing to retrieve internal package representation.
    481    *
    482    * <p>This will allow to modify the package in a way visible to Robolectric, as this is
    483    * Robolectric's internal full package representation.
    484    *
    485    * <p>Note that maybe a better way is to just modify the test manifest to make those modifications
    486    * in a standard way.
    487    *
    488    * <p>Retrieving package info using {@link PackageManager#getPackageInfo} / {@link
    489    * PackageManager#getApplicationInfo} will return defensive copies that will be stripped out of
    490    * information according to provided flags. Don't use it to modify Robolectric state.
    491    */
    492   public PackageInfo getInternalMutablePackageInfo(String packageName) {
    493     return packageInfos.get(packageName);
    494   }
    495 
    496   /** @deprecated Use {@link #getInternalMutablePackageInfo} instead. It has better name. */
    497   @Deprecated
    498   public PackageInfo getPackageInfoForTesting(String packageName) {
    499     return getInternalMutablePackageInfo(packageName);
    500   }
    501 
    502   public void addPermissionInfo(PermissionInfo permissionInfo) {
    503     extraPermissions.put(permissionInfo.name, permissionInfo);
    504   }
    505 
    506   /**
    507    * Adds {@code packageName} to the list of changed packages for the particular {@code
    508    * sequenceNumber}.
    509    *
    510    * @param sequenceNumber has to be >= 0
    511    * @param packageName name of the package that was changed
    512    */
    513   public void addChangedPackage(int sequenceNumber, String packageName) {
    514     if (sequenceNumber < 0) {
    515       return;
    516     }
    517     sequenceNumberChangedPackagesMap.put(sequenceNumber, packageName);
    518   }
    519 
    520   /**
    521    * Allows overriding or adding permission-group elements. These would be otherwise specified by
    522    * either (the
    523    * system)[https://developer.android.com/guide/topics/permissions/requesting.html#perm-groups] or
    524    * by (the app
    525    * itself)[https://developer.android.com/guide/topics/manifest/permission-group-element.html], as
    526    * part of its manifest
    527    *
    528    * <p>{@link android.content.pm.PackageParser.PermissionGroup}s added through this method have
    529    * precedence over those specified with the same name by one of the aforementioned methods.
    530    *
    531    * @see PackageManager#getAllPermissionGroups(int)
    532    * @see PackageManager#getPermissionGroupInfo(String, int)
    533    */
    534   public void addPermissionGroupInfo(PermissionGroupInfo permissionGroupInfo) {
    535     extraPermissionGroups.put(permissionGroupInfo.name, permissionGroupInfo);
    536   }
    537 
    538   public void removePackage(String packageName) {
    539     packages.remove(packageName);
    540     packageInfos.remove(packageName);
    541 
    542     packageSettings.remove(packageName);
    543   }
    544 
    545   public void setSystemFeature(String name, boolean supported) {
    546     systemFeatureList.put(name, supported);
    547   }
    548 
    549   public void addDrawableResolution(String packageName, int resourceId, Drawable drawable) {
    550     drawables.put(new Pair(packageName, resourceId), drawable);
    551   }
    552 
    553   public void setNameForUid(int uid, String name) {
    554     namesForUid.put(uid, name);
    555   }
    556 
    557   public void setPackagesForCallingUid(String... packagesForCallingUid) {
    558     packagesForUid.put(Binder.getCallingUid(), packagesForCallingUid);
    559     for (String packageName : packagesForCallingUid) {
    560       uidForPackage.put(packageName, Binder.getCallingUid());
    561     }
    562   }
    563 
    564   public void setPackagesForUid(int uid, String... packagesForCallingUid) {
    565     packagesForUid.put(uid, packagesForCallingUid);
    566     for (String packageName : packagesForCallingUid) {
    567       uidForPackage.put(packageName, uid);
    568     }
    569   }
    570 
    571   @Implementation
    572   @Nullable
    573   protected String[] getPackagesForUid(int uid) {
    574     return packagesForUid.get(uid);
    575   }
    576 
    577   public void setPackageArchiveInfo(String archiveFilePath, PackageInfo packageInfo) {
    578     packageArchiveInfo.put(archiveFilePath, packageInfo);
    579   }
    580 
    581   public int getVerificationResult(int id) {
    582     Integer result = verificationResults.get(id);
    583     if (result == null) {
    584       // 0 isn't a "valid" result, so we can check for the case when verification isn't
    585       // called, if needed
    586       return 0;
    587     }
    588     return result;
    589   }
    590 
    591   public long getVerificationExtendedTimeout(int id) {
    592     Long result = verificationTimeoutExtension.get(id);
    593     if (result == null) {
    594       return 0;
    595     }
    596     return result;
    597   }
    598 
    599   public void setShouldShowRequestPermissionRationale(String permission, boolean show) {
    600     permissionRationaleMap.put(permission, show);
    601   }
    602 
    603   public void addSystemAvailableFeature(FeatureInfo featureInfo) {
    604     systemAvailableFeatures.add(featureInfo);
    605   }
    606 
    607   public void clearSystemAvailableFeatures() {
    608     systemAvailableFeatures.clear();
    609   }
    610 
    611   /** Adds a value to be returned by {@link PackageManager#getSystemSharedLibraryNames()}. */
    612   public void addSystemSharedLibraryName(String name) {
    613     systemSharedLibraryNames.add(name);
    614   }
    615 
    616   /** Clears the values returned by {@link PackageManager#getSystemSharedLibraryNames()}. */
    617   public void clearSystemSharedLibraryNames() {
    618     systemSharedLibraryNames.clear();
    619   }
    620 
    621   public void addCurrentToCannonicalName(String currentName, String canonicalName) {
    622     currentToCanonicalNames.put(currentName, canonicalName);
    623   }
    624 
    625   /**
    626    * Sets if the {@link PackageManager} is allowed to request package installs through package
    627    * installer.
    628    */
    629   public void setCanRequestPackageInstalls(boolean canRequestPackageInstalls) {
    630     ShadowPackageManager.canRequestPackageInstalls = canRequestPackageInstalls;
    631   }
    632 
    633   @Implementation(minSdk = N)
    634   protected List<ResolveInfo> queryBroadcastReceiversAsUser(
    635       Intent intent, int flags, UserHandle userHandle) {
    636     return null;
    637   }
    638 
    639   @Implementation(minSdk = JELLY_BEAN_MR1)
    640   protected List<ResolveInfo> queryBroadcastReceivers(
    641       Intent intent, int flags, @UserIdInt int userId) {
    642     return null;
    643   }
    644 
    645   @Implementation
    646   protected PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) {
    647     List<PackageInfo> result = new ArrayList<>();
    648     for (PackageInfo packageInfo : packageInfos.values()) {
    649       if (applicationEnabledSettingMap.get(packageInfo.packageName)
    650               != COMPONENT_ENABLED_STATE_DISABLED
    651           || (flags & MATCH_UNINSTALLED_PACKAGES) == MATCH_UNINSTALLED_PACKAGES) {
    652         result.add(packageInfo);
    653       }
    654     }
    655 
    656     List<PackageInfo> packages = result;
    657     for (PackageInfo aPackage : packages) {
    658       ApplicationInfo appInfo = aPackage.applicationInfo;
    659       if (appInfo != null && archiveFilePath.equals(appInfo.sourceDir)) {
    660         return aPackage;
    661       }
    662     }
    663     return null;
    664   }
    665 
    666   @Implementation
    667   protected void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer) {}
    668 
    669   @Implementation
    670   protected void freeStorage(long freeStorageSize, IntentSender pi) {}
    671 
    672   /**
    673    * Runs the callbacks pending from calls to {@link PackageManager#deletePackage(String,
    674    * IPackageDeleteObserver, int)}
    675    */
    676   public void doPendingUninstallCallbacks() {
    677     boolean hasDeletePackagesPermission = false;
    678     String[] requestedPermissions =
    679         packageInfos.get(RuntimeEnvironment.application.getPackageName()).requestedPermissions;
    680     if (requestedPermissions != null) {
    681       for (String permission : requestedPermissions) {
    682         if (Manifest.permission.DELETE_PACKAGES.equals(permission)) {
    683           hasDeletePackagesPermission = true;
    684           break;
    685         }
    686       }
    687     }
    688 
    689     for (String packageName : pendingDeleteCallbacks.keySet()) {
    690       int resultCode = PackageManager.DELETE_FAILED_INTERNAL_ERROR;
    691 
    692       PackageInfo removed = packageInfos.get(packageName);
    693       if (hasDeletePackagesPermission && removed != null) {
    694         packageInfos.remove(packageName);
    695 
    696         packageSettings.remove(packageName);
    697 
    698         deletedPackages.add(packageName);
    699         resultCode = PackageManager.DELETE_SUCCEEDED;
    700       }
    701 
    702       try {
    703         pendingDeleteCallbacks.get(packageName).packageDeleted(packageName, resultCode);
    704       } catch (RemoteException e) {
    705         throw new RuntimeException(e);
    706       }
    707     }
    708     pendingDeleteCallbacks.clear();
    709   }
    710 
    711   /**
    712    * Returns package names successfully deleted with {@link PackageManager#deletePackage(String,
    713    * IPackageDeleteObserver, int)} Note that like real {@link PackageManager} the calling context
    714    * must have {@link android.Manifest.permission#DELETE_PACKAGES} permission set.
    715    */
    716   public Set<String> getDeletedPackages() {
    717     return deletedPackages;
    718   }
    719 
    720   protected List<ResolveInfo> queryOverriddenIntents(Intent intent, int flags) {
    721     List<ResolveInfo> overrides = resolveInfoForIntent.get(intent);
    722     if (overrides == null) {
    723       return Collections.emptyList();
    724     }
    725     List<ResolveInfo> result = new ArrayList<>(overrides.size());
    726     for (ResolveInfo resolveInfo : overrides) {
    727       result.add(ShadowResolveInfo.newResolveInfo(resolveInfo));
    728     }
    729     return result;
    730   }
    731 
    732   /**
    733    * Internal use only.
    734    *
    735    * @param appPackage
    736    */
    737   public void addPackageInternal(Package appPackage) {
    738     int flags =
    739         GET_ACTIVITIES
    740             | GET_RECEIVERS
    741             | GET_SERVICES
    742             | GET_PROVIDERS
    743             | GET_INSTRUMENTATION
    744             | GET_INTENT_FILTERS
    745             | GET_SIGNATURES
    746             | GET_RESOLVED_FILTER
    747             | GET_META_DATA
    748             | GET_GIDS
    749             | MATCH_DISABLED_COMPONENTS
    750             | GET_SHARED_LIBRARY_FILES
    751             | GET_URI_PERMISSION_PATTERNS
    752             | GET_PERMISSIONS
    753             | MATCH_UNINSTALLED_PACKAGES
    754             | GET_CONFIGURATIONS
    755             | MATCH_DISABLED_UNTIL_USED_COMPONENTS
    756             | MATCH_DIRECT_BOOT_UNAWARE
    757             | MATCH_DIRECT_BOOT_AWARE;
    758 
    759     packages.put(appPackage.packageName, appPackage);
    760     PackageInfo packageInfo;
    761     if (RuntimeEnvironment.getApiLevel() >= M) {
    762       packageInfo =
    763           PackageParser.generatePackageInfo(
    764               appPackage,
    765               new int[] {0},
    766               flags,
    767               0,
    768               0,
    769               new HashSet<String>(),
    770               new PackageUserState());
    771     } else if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP_MR1) {
    772       packageInfo =
    773           ReflectionHelpers.callStaticMethod(
    774               PackageParser.class,
    775               "generatePackageInfo",
    776               ReflectionHelpers.ClassParameter.from(Package.class, appPackage),
    777               ReflectionHelpers.ClassParameter.from(int[].class, new int[] {0}),
    778               ReflectionHelpers.ClassParameter.from(int.class, flags),
    779               ReflectionHelpers.ClassParameter.from(long.class, 0L),
    780               ReflectionHelpers.ClassParameter.from(long.class, 0L),
    781               ReflectionHelpers.ClassParameter.from(ArraySet.class, new ArraySet<>()),
    782               ReflectionHelpers.ClassParameter.from(
    783                   PackageUserState.class, new PackageUserState()));
    784     } else if (RuntimeEnvironment.getApiLevel() >= JELLY_BEAN_MR1) {
    785       packageInfo =
    786           ReflectionHelpers.callStaticMethod(
    787               PackageParser.class,
    788               "generatePackageInfo",
    789               ReflectionHelpers.ClassParameter.from(Package.class, appPackage),
    790               ReflectionHelpers.ClassParameter.from(int[].class, new int[] {0}),
    791               ReflectionHelpers.ClassParameter.from(int.class, flags),
    792               ReflectionHelpers.ClassParameter.from(long.class, 0L),
    793               ReflectionHelpers.ClassParameter.from(long.class, 0L),
    794               ReflectionHelpers.ClassParameter.from(HashSet.class, new HashSet<>()),
    795               ReflectionHelpers.ClassParameter.from(
    796                   PackageUserState.class, new PackageUserState()));
    797     } else {
    798       packageInfo =
    799           ReflectionHelpers.callStaticMethod(
    800               PackageParser.class,
    801               "generatePackageInfo",
    802               ReflectionHelpers.ClassParameter.from(Package.class, appPackage),
    803               ReflectionHelpers.ClassParameter.from(int[].class, new int[] {0}),
    804               ReflectionHelpers.ClassParameter.from(int.class, flags),
    805               ReflectionHelpers.ClassParameter.from(long.class, 0L),
    806               ReflectionHelpers.ClassParameter.from(long.class, 0L),
    807               ReflectionHelpers.ClassParameter.from(HashSet.class, new HashSet<>()));
    808     }
    809 
    810     packageInfo.applicationInfo.uid = Process.myUid();
    811     packageInfo.applicationInfo.dataDir =
    812         RuntimeEnvironment.getTempDirectory()
    813             .createIfNotExists(packageInfo.packageName + "-dataDir")
    814             .toString();
    815     installPackage(packageInfo);
    816   }
    817 
    818   public static class IntentComparator implements Comparator<Intent> {
    819 
    820     @Override
    821     public int compare(Intent i1, Intent i2) {
    822       if (i1 == null && i2 == null) return 0;
    823       if (i1 == null && i2 != null) return -1;
    824       if (i1 != null && i2 == null) return 1;
    825       if (i1.equals(i2)) return 0;
    826       String action1 = i1.getAction();
    827       String action2 = i2.getAction();
    828       if (action1 == null && action2 != null) return -1;
    829       if (action1 != null && action2 == null) return 1;
    830       if (action1 != null && action2 != null) {
    831         if (!action1.equals(action2)) {
    832           return action1.compareTo(action2);
    833         }
    834       }
    835       Uri data1 = i1.getData();
    836       Uri data2 = i2.getData();
    837       if (data1 == null && data2 != null) return -1;
    838       if (data1 != null && data2 == null) return 1;
    839       if (data1 != null && data2 != null) {
    840         if (!data1.equals(data2)) {
    841           return data1.compareTo(data2);
    842         }
    843       }
    844       ComponentName component1 = i1.getComponent();
    845       ComponentName component2 = i2.getComponent();
    846       if (component1 == null && component2 != null) return -1;
    847       if (component1 != null && component2 == null) return 1;
    848       if (component1 != null && component2 != null) {
    849         if (!component1.equals(component2)) {
    850           return component1.compareTo(component2);
    851         }
    852       }
    853       String package1 = i1.getPackage();
    854       String package2 = i2.getPackage();
    855       if (package1 == null && package2 != null) return -1;
    856       if (package1 != null && package2 == null) return 1;
    857       if (package1 != null && package2 != null) {
    858         if (!package1.equals(package2)) {
    859           return package1.compareTo(package2);
    860         }
    861       }
    862       Set<String> categories1 = i1.getCategories();
    863       Set<String> categories2 = i2.getCategories();
    864       if (categories1 == null) return categories2 == null ? 0 : -1;
    865       if (categories2 == null) return 1;
    866       if (categories1.size() > categories2.size()) return 1;
    867       if (categories1.size() < categories2.size()) return -1;
    868       String[] array1 = categories1.toArray(new String[0]);
    869       String[] array2 = categories2.toArray(new String[0]);
    870       Arrays.sort(array1);
    871       Arrays.sort(array2);
    872       for (int i = 0; i < array1.length; ++i) {
    873         int val = array1[i].compareTo(array2[i]);
    874         if (val != 0) return val;
    875       }
    876       return 0;
    877     }
    878   }
    879 
    880   /**
    881    * This class wraps {@link IntentFilter} so it has reasonable {@link #equals} and {@link
    882    * #hashCode} methods.
    883    */
    884   protected static class IntentFilterWrapper {
    885     final IntentFilter filter;
    886     private final HashSet<String> actions = new HashSet<>();
    887     private HashSet<String> categories = new HashSet<>();
    888     private HashSet<String> dataSchemes = new HashSet<>();
    889     private HashSet<String> dataSchemeSpecificParts = new HashSet<>();
    890     private HashSet<String> dataAuthorities = new HashSet<>();
    891     private HashSet<String> dataPaths = new HashSet<>();
    892     private HashSet<String> dataTypes = new HashSet<>();
    893 
    894     public IntentFilterWrapper(IntentFilter filter) {
    895       this.filter = filter;
    896       if (filter == null) {
    897         return;
    898       }
    899       for (int i = 0; i < filter.countActions(); i++) {
    900         actions.add(filter.getAction(i));
    901       }
    902       for (int i = 0; i < filter.countCategories(); i++) {
    903         categories.add(filter.getCategory(i));
    904       }
    905       for (int i = 0; i < filter.countDataAuthorities(); i++) {
    906         AuthorityEntry dataAuthority = filter.getDataAuthority(i);
    907         dataAuthorities.add(dataAuthority.getHost() + ":" + dataAuthority.getPort());
    908       }
    909       for (int i = 0; i < filter.countDataPaths(); i++) {
    910         PatternMatcher dataPath = filter.getDataPath(i);
    911         dataPaths.add(dataPath.toString());
    912       }
    913       for (int i = 0; i < filter.countDataSchemes(); i++) {
    914         dataSchemes.add(filter.getDataScheme(i));
    915       }
    916       if (VERSION.SDK_INT >= KITKAT) {
    917         for (int i = 0; i < filter.countDataSchemeSpecificParts(); i++) {
    918           dataSchemeSpecificParts.add(filter.getDataSchemeSpecificPart(i).toString());
    919         }
    920       }
    921       for (int i = 0; i < filter.countDataTypes(); i++) {
    922         dataTypes.add(filter.getDataType(i));
    923       }
    924     }
    925 
    926     @Override
    927     public boolean equals(Object o) {
    928       if (this == o) {
    929         return true;
    930       }
    931       if (!(o instanceof IntentFilterWrapper)) {
    932         return false;
    933       }
    934       IntentFilterWrapper that = (IntentFilterWrapper) o;
    935       if (filter == null && that.filter == null) {
    936         return true;
    937       }
    938       if (filter == null || that.filter == null) {
    939         return false;
    940       }
    941       return filter.getPriority() == that.filter.getPriority()
    942           && Objects.equals(actions, that.actions)
    943           && Objects.equals(categories, that.categories)
    944           && Objects.equals(dataSchemes, that.dataSchemes)
    945           && Objects.equals(dataSchemeSpecificParts, that.dataSchemeSpecificParts)
    946           && Objects.equals(dataAuthorities, that.dataAuthorities)
    947           && Objects.equals(dataPaths, that.dataPaths)
    948           && Objects.equals(dataTypes, that.dataTypes);
    949     }
    950 
    951     @Override
    952     public int hashCode() {
    953       return Objects.hash(
    954           filter == null ? null : filter.getPriority(),
    955           actions,
    956           categories,
    957           dataSchemes,
    958           dataSchemeSpecificParts,
    959           dataAuthorities,
    960           dataPaths,
    961           dataTypes);
    962     }
    963 
    964     public IntentFilter getFilter() {
    965       return filter;
    966     }
    967   }
    968 
    969   /** Compares {@link ResolveInfo}, where better is bigger. */
    970   static class ResolveInfoComparator implements Comparator<ResolveInfo> {
    971 
    972     private final HashSet<ComponentName> preferredComponents;
    973 
    974     public ResolveInfoComparator(HashSet<ComponentName> preferredComponents) {
    975       this.preferredComponents = preferredComponents;
    976     }
    977 
    978     @Override
    979     public int compare(ResolveInfo o1, ResolveInfo o2) {
    980       if (o1 == null && o2 == null) {
    981         return 0;
    982       }
    983       if (o1 == null) {
    984         return -1;
    985       }
    986       if (o2 == null) {
    987         return 1;
    988       }
    989       boolean o1isPreferred = isPreferred(o1);
    990       boolean o2isPreferred = isPreferred(o2);
    991       if (o1isPreferred != o2isPreferred) {
    992         return Boolean.compare(o1isPreferred, o2isPreferred);
    993       }
    994       if (o1.preferredOrder != o2.preferredOrder) {
    995         return Integer.compare(o1.preferredOrder, o2.preferredOrder);
    996       }
    997       if (o1.priority != o2.priority) {
    998         return Integer.compare(o1.priority, o2.priority);
    999       }
   1000       return 0;
   1001     }
   1002 
   1003     private boolean isPreferred(ResolveInfo resolveInfo) {
   1004       return resolveInfo.activityInfo != null
   1005           && resolveInfo.activityInfo.packageName != null
   1006           && resolveInfo.activityInfo.name != null
   1007           && preferredComponents.contains(
   1008               new ComponentName(
   1009                   resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name));
   1010     }
   1011   }
   1012 
   1013   protected static class ComponentState {
   1014     public int newState;
   1015     public int flags;
   1016 
   1017     public ComponentState(int newState, int flags) {
   1018       this.newState = newState;
   1019       this.flags = flags;
   1020     }
   1021   }
   1022 
   1023   /**
   1024    * Get list of intent filters defined for given activity.
   1025    *
   1026    * @param componentName Name of the activity whose intent filters are to be retrieved
   1027    * @return the activity's intent filters
   1028    */
   1029   public List<IntentFilter> getIntentFiltersForActivity(ComponentName componentName)
   1030       throws NameNotFoundException {
   1031     return getIntentFiltersForComponent(getAppPackage(componentName).activities, componentName);
   1032   }
   1033 
   1034   /**
   1035    * Get list of intent filters defined for given service.
   1036    *
   1037    * @param componentName Name of the service whose intent filters are to be retrieved
   1038    * @return the service's intent filters
   1039    */
   1040   public List<IntentFilter> getIntentFiltersForService(ComponentName componentName)
   1041       throws NameNotFoundException {
   1042     return getIntentFiltersForComponent(getAppPackage(componentName).services, componentName);
   1043   }
   1044 
   1045   /**
   1046    * Get list of intent filters defined for given receiver.
   1047    *
   1048    * @param componentName Name of the receiver whose intent filters are to be retrieved
   1049    * @return the receiver's intent filters
   1050    */
   1051   public List<IntentFilter> getIntentFiltersForReceiver(ComponentName componentName)
   1052       throws NameNotFoundException {
   1053     return getIntentFiltersForComponent(getAppPackage(componentName).receivers, componentName);
   1054   }
   1055 
   1056   private static List<IntentFilter> getIntentFiltersForComponent(
   1057       List<? extends Component> components, ComponentName componentName)
   1058       throws NameNotFoundException {
   1059     for (Component component : components) {
   1060       if (component.getComponentName().equals(componentName)) {
   1061         return component.intents;
   1062       }
   1063     }
   1064     throw new NameNotFoundException("unknown component " + componentName);
   1065   }
   1066 
   1067   private static Package getAppPackage(ComponentName componentName) throws NameNotFoundException {
   1068     Package appPackage = packages.get(componentName.getPackageName());
   1069     if (appPackage == null) {
   1070       throw new NameNotFoundException("unknown package " + componentName.getPackageName());
   1071     }
   1072     return appPackage;
   1073   }
   1074 
   1075   /**
   1076    * Returns the current {@link PackageSetting} of {@code packageName}.
   1077    *
   1078    * <p>If {@code packageName} is not present in this {@link ShadowPackageManager}, this method will
   1079    * return null.
   1080    */
   1081   public PackageSetting getPackageSetting(String packageName) {
   1082     PackageSetting setting = packageSettings.get(packageName);
   1083     return setting == null ? null : new PackageSetting(setting);
   1084   }
   1085 
   1086   @Resetter
   1087   public static void reset() {
   1088     permissionRationaleMap.clear();
   1089     systemAvailableFeatures.clear();
   1090     systemSharedLibraryNames.clear();
   1091     packageInfos.clear();
   1092     packages.clear();
   1093     packageArchiveInfo.clear();
   1094     packageStatsMap.clear();
   1095     packageInstallerMap.clear();
   1096     packagesForUid.clear();
   1097     uidForPackage.clear();
   1098     namesForUid.clear();
   1099     verificationResults.clear();
   1100     verificationTimeoutExtension.clear();
   1101     currentToCanonicalNames.clear();
   1102     componentList.clear();
   1103     drawableList.clear();
   1104     applicationIcons.clear();
   1105     unbadgedApplicationIcons.clear();
   1106     systemFeatureList.clear();
   1107     preferredActivities.clear();
   1108     drawables.clear();
   1109     applicationEnabledSettingMap.clear();
   1110     extraPermissions.clear();
   1111     extraPermissionGroups.clear();
   1112     resources.clear();
   1113     resolveInfoForIntent.clear();
   1114     deletedPackages.clear();
   1115     pendingDeleteCallbacks.clear();
   1116     hiddenPackages.clear();
   1117     sequenceNumberChangedPackagesMap.clear();
   1118 
   1119     packageSettings.clear();
   1120   }
   1121 }
   1122