Home | History | Annotate | Download | only in pm
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.content.pm;
     18 
     19 import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
     20 import static android.content.pm.ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
     21 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
     22 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
     23 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
     24 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
     25 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
     26 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
     27 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
     28 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     29 import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
     30 import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
     31 import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
     32 import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
     33 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
     34 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
     35 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
     36 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
     37 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
     38 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
     39 import static android.os.Build.VERSION_CODES.O;
     40 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
     41 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
     42 
     43 import android.annotation.IntDef;
     44 import android.annotation.IntRange;
     45 import android.annotation.NonNull;
     46 import android.annotation.Nullable;
     47 import android.annotation.TestApi;
     48 import android.app.ActivityManager;
     49 import android.content.ComponentName;
     50 import android.content.Intent;
     51 import android.content.IntentFilter;
     52 import android.content.pm.PackageParserCacheHelper.ReadHelper;
     53 import android.content.pm.PackageParserCacheHelper.WriteHelper;
     54 import android.content.pm.split.DefaultSplitAssetLoader;
     55 import android.content.pm.split.SplitAssetDependencyLoader;
     56 import android.content.pm.split.SplitAssetLoader;
     57 import android.content.res.ApkAssets;
     58 import android.content.res.AssetManager;
     59 import android.content.res.Configuration;
     60 import android.content.res.Resources;
     61 import android.content.res.TypedArray;
     62 import android.content.res.XmlResourceParser;
     63 import android.os.Build;
     64 import android.os.Bundle;
     65 import android.os.FileUtils;
     66 import android.os.Parcel;
     67 import android.os.Parcelable;
     68 import android.os.PatternMatcher;
     69 import android.os.SystemClock;
     70 import android.os.SystemProperties;
     71 import android.os.Trace;
     72 import android.os.UserHandle;
     73 import android.os.storage.StorageManager;
     74 import android.system.ErrnoException;
     75 import android.system.OsConstants;
     76 import android.system.StructStat;
     77 import android.text.TextUtils;
     78 import android.util.ArrayMap;
     79 import android.util.ArraySet;
     80 import android.util.AttributeSet;
     81 import android.util.Base64;
     82 import android.util.ByteStringUtils;
     83 import android.util.DisplayMetrics;
     84 import android.util.Log;
     85 import android.util.PackageUtils;
     86 import android.util.Pair;
     87 import android.util.Slog;
     88 import android.util.SparseArray;
     89 import android.util.TypedValue;
     90 import android.util.apk.ApkSignatureVerifier;
     91 import android.view.Gravity;
     92 
     93 import com.android.internal.R;
     94 import com.android.internal.annotations.VisibleForTesting;
     95 import com.android.internal.os.ClassLoaderFactory;
     96 import com.android.internal.util.ArrayUtils;
     97 import com.android.internal.util.XmlUtils;
     98 
     99 import libcore.io.IoUtils;
    100 import libcore.util.EmptyArray;
    101 
    102 import org.xmlpull.v1.XmlPullParser;
    103 import org.xmlpull.v1.XmlPullParserException;
    104 
    105 import java.io.File;
    106 import java.io.FileDescriptor;
    107 import java.io.FileOutputStream;
    108 import java.io.IOException;
    109 import java.io.PrintWriter;
    110 import java.lang.annotation.Retention;
    111 import java.lang.annotation.RetentionPolicy;
    112 import java.lang.reflect.Constructor;
    113 import java.security.KeyFactory;
    114 import java.security.NoSuchAlgorithmException;
    115 import java.security.PublicKey;
    116 import java.security.cert.CertificateException;
    117 import java.security.spec.EncodedKeySpec;
    118 import java.security.spec.InvalidKeySpecException;
    119 import java.security.spec.X509EncodedKeySpec;
    120 import java.util.ArrayList;
    121 import java.util.Arrays;
    122 import java.util.Collections;
    123 import java.util.Comparator;
    124 import java.util.Iterator;
    125 import java.util.List;
    126 import java.util.Set;
    127 import java.util.UUID;
    128 import java.util.concurrent.atomic.AtomicInteger;
    129 
    130 /**
    131  * Parser for package files (APKs) on disk. This supports apps packaged either
    132  * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
    133  * APKs in a single directory.
    134  * <p>
    135  * Apps packaged as multiple APKs always consist of a single "base" APK (with a
    136  * {@code null} split name) and zero or more "split" APKs (with unique split
    137  * names). Any subset of those split APKs are a valid install, as long as the
    138  * following constraints are met:
    139  * <ul>
    140  * <li>All APKs must have the exact same package name, version code, and signing
    141  * certificates.
    142  * <li>All APKs must have unique split names.
    143  * <li>All installations must contain a single base APK.
    144  * </ul>
    145  *
    146  * @hide
    147  */
    148 public class PackageParser {
    149     private static final boolean DEBUG_JAR = false;
    150     private static final boolean DEBUG_PARSER = false;
    151     private static final boolean DEBUG_BACKUP = false;
    152     private static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE;
    153     private static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100;
    154 
    155     private static final String PROPERTY_CHILD_PACKAGES_ENABLED =
    156             "persist.sys.child_packages_enabled";
    157 
    158     private static final boolean MULTI_PACKAGE_APK_ENABLED = Build.IS_DEBUGGABLE &&
    159             SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false);
    160 
    161     private static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f;
    162 
    163     // TODO: switch outError users to PackageParserException
    164     // TODO: refactor "codePath" to "apkPath"
    165 
    166     /** File name in an APK for the Android manifest. */
    167     public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
    168 
    169     /** Path prefix for apps on expanded storage */
    170     private static final String MNT_EXPAND = "/mnt/expand/";
    171 
    172     private static final String TAG_MANIFEST = "manifest";
    173     private static final String TAG_APPLICATION = "application";
    174     private static final String TAG_PACKAGE_VERIFIER = "package-verifier";
    175     private static final String TAG_OVERLAY = "overlay";
    176     private static final String TAG_KEY_SETS = "key-sets";
    177     private static final String TAG_PERMISSION_GROUP = "permission-group";
    178     private static final String TAG_PERMISSION = "permission";
    179     private static final String TAG_PERMISSION_TREE = "permission-tree";
    180     private static final String TAG_USES_PERMISSION = "uses-permission";
    181     private static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
    182     private static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23";
    183     private static final String TAG_USES_CONFIGURATION = "uses-configuration";
    184     private static final String TAG_USES_FEATURE = "uses-feature";
    185     private static final String TAG_FEATURE_GROUP = "feature-group";
    186     private static final String TAG_USES_SDK = "uses-sdk";
    187     private static final String TAG_SUPPORT_SCREENS = "supports-screens";
    188     private static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
    189     private static final String TAG_INSTRUMENTATION = "instrumentation";
    190     private static final String TAG_ORIGINAL_PACKAGE = "original-package";
    191     private static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
    192     private static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
    193     private static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
    194     private static final String TAG_SUPPORTS_INPUT = "supports-input";
    195     private static final String TAG_EAT_COMMENT = "eat-comment";
    196     private static final String TAG_PACKAGE = "package";
    197     private static final String TAG_RESTRICT_UPDATE = "restrict-update";
    198     private static final String TAG_USES_SPLIT = "uses-split";
    199 
    200     private static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
    201 
    202     /**
    203      * Bit mask of all the valid bits that can be set in recreateOnConfigChanges.
    204      * @hide
    205      */
    206     private static final int RECREATE_ON_CONFIG_CHANGES_MASK =
    207             ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC;
    208 
    209     // These are the tags supported by child packages
    210     private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>();
    211     static {
    212         CHILD_PACKAGE_TAGS.add(TAG_APPLICATION);
    213         CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION);
    214         CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_M);
    215         CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_23);
    216         CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION);
    217         CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE);
    218         CHILD_PACKAGE_TAGS.add(TAG_FEATURE_GROUP);
    219         CHILD_PACKAGE_TAGS.add(TAG_USES_SDK);
    220         CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS);
    221         CHILD_PACKAGE_TAGS.add(TAG_INSTRUMENTATION);
    222         CHILD_PACKAGE_TAGS.add(TAG_USES_GL_TEXTURE);
    223         CHILD_PACKAGE_TAGS.add(TAG_COMPATIBLE_SCREENS);
    224         CHILD_PACKAGE_TAGS.add(TAG_SUPPORTS_INPUT);
    225         CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
    226     }
    227 
    228     private static final boolean LOG_UNSAFE_BROADCASTS = false;
    229 
    230     /**
    231      * Total number of packages that were read from the cache.  We use it only for logging.
    232      */
    233     public static final AtomicInteger sCachedPackageReadCount = new AtomicInteger();
    234 
    235     // Set of broadcast actions that are safe for manifest receivers
    236     private static final Set<String> SAFE_BROADCASTS = new ArraySet<>();
    237     static {
    238         SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED);
    239     }
    240 
    241     /** @hide */
    242     public static final String APK_FILE_EXTENSION = ".apk";
    243 
    244     /** @hide */
    245     public static class NewPermissionInfo {
    246         public final String name;
    247         public final int sdkVersion;
    248         public final int fileVersion;
    249 
    250         public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
    251             this.name = name;
    252             this.sdkVersion = sdkVersion;
    253             this.fileVersion = fileVersion;
    254         }
    255     }
    256 
    257     /** @hide */
    258     public static class SplitPermissionInfo {
    259         public final String rootPerm;
    260         public final String[] newPerms;
    261         public final int targetSdk;
    262 
    263         public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
    264             this.rootPerm = rootPerm;
    265             this.newPerms = newPerms;
    266             this.targetSdk = targetSdk;
    267         }
    268     }
    269 
    270     /**
    271      * List of new permissions that have been added since 1.0.
    272      * NOTE: These must be declared in SDK version order, with permissions
    273      * added to older SDKs appearing before those added to newer SDKs.
    274      * If sdkVersion is 0, then this is not a permission that we want to
    275      * automatically add to older apps, but we do want to allow it to be
    276      * granted during a platform update.
    277      * @hide
    278      */
    279     public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
    280         new PackageParser.NewPermissionInfo[] {
    281             new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
    282                     android.os.Build.VERSION_CODES.DONUT, 0),
    283             new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
    284                     android.os.Build.VERSION_CODES.DONUT, 0)
    285     };
    286 
    287     /**
    288      * List of permissions that have been split into more granular or dependent
    289      * permissions.
    290      * @hide
    291      */
    292     public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
    293         new PackageParser.SplitPermissionInfo[] {
    294             // READ_EXTERNAL_STORAGE is always required when an app requests
    295             // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
    296             // write access without read access.  The hack here with the target
    297             // target SDK version ensures that this grant is always done.
    298             new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
    299                     new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
    300                     android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
    301             new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
    302                     new String[] { android.Manifest.permission.READ_CALL_LOG },
    303                     android.os.Build.VERSION_CODES.JELLY_BEAN),
    304             new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
    305                     new String[] { android.Manifest.permission.WRITE_CALL_LOG },
    306                     android.os.Build.VERSION_CODES.JELLY_BEAN)
    307     };
    308 
    309     /**
    310      * @deprecated callers should move to explicitly passing around source path.
    311      */
    312     @Deprecated
    313     private String mArchiveSourcePath;
    314 
    315     private String[] mSeparateProcesses;
    316     private boolean mOnlyCoreApps;
    317     private DisplayMetrics mMetrics;
    318     private Callback mCallback;
    319     private File mCacheDir;
    320 
    321     private static final int SDK_VERSION = Build.VERSION.SDK_INT;
    322     private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
    323 
    324     private int mParseError = PackageManager.INSTALL_SUCCEEDED;
    325 
    326     private static boolean sCompatibilityModeEnabled = true;
    327     private static final int PARSE_DEFAULT_INSTALL_LOCATION =
    328             PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
    329     private static final int PARSE_DEFAULT_TARGET_SANDBOX = 1;
    330 
    331     static class ParsePackageItemArgs {
    332         final Package owner;
    333         final String[] outError;
    334         final int nameRes;
    335         final int labelRes;
    336         final int iconRes;
    337         final int roundIconRes;
    338         final int logoRes;
    339         final int bannerRes;
    340 
    341         String tag;
    342         TypedArray sa;
    343 
    344         ParsePackageItemArgs(Package _owner, String[] _outError,
    345                 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
    346                 int _bannerRes) {
    347             owner = _owner;
    348             outError = _outError;
    349             nameRes = _nameRes;
    350             labelRes = _labelRes;
    351             iconRes = _iconRes;
    352             logoRes = _logoRes;
    353             bannerRes = _bannerRes;
    354             roundIconRes = _roundIconRes;
    355         }
    356     }
    357 
    358     /** @hide */
    359     @VisibleForTesting
    360     public static class ParseComponentArgs extends ParsePackageItemArgs {
    361         final String[] sepProcesses;
    362         final int processRes;
    363         final int descriptionRes;
    364         final int enabledRes;
    365         int flags;
    366 
    367         public ParseComponentArgs(Package _owner, String[] _outError,
    368                 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
    369                 int _bannerRes,
    370                 String[] _sepProcesses, int _processRes,
    371                 int _descriptionRes, int _enabledRes) {
    372             super(_owner, _outError, _nameRes, _labelRes, _iconRes, _roundIconRes, _logoRes,
    373                     _bannerRes);
    374             sepProcesses = _sepProcesses;
    375             processRes = _processRes;
    376             descriptionRes = _descriptionRes;
    377             enabledRes = _enabledRes;
    378         }
    379     }
    380 
    381     /**
    382      * Lightweight parsed details about a single package.
    383      */
    384     public static class PackageLite {
    385         public final String packageName;
    386         public final int versionCode;
    387         public final int versionCodeMajor;
    388         public final int installLocation;
    389         public final VerifierInfo[] verifiers;
    390 
    391         /** Names of any split APKs, ordered by parsed splitName */
    392         public final String[] splitNames;
    393 
    394         /** Names of any split APKs that are features. Ordered by splitName */
    395         public final boolean[] isFeatureSplits;
    396 
    397         /** Dependencies of any split APKs, ordered by parsed splitName */
    398         public final String[] usesSplitNames;
    399         public final String[] configForSplit;
    400 
    401         /**
    402          * Path where this package was found on disk. For monolithic packages
    403          * this is path to single base APK file; for cluster packages this is
    404          * path to the cluster directory.
    405          */
    406         public final String codePath;
    407 
    408         /** Path of base APK */
    409         public final String baseCodePath;
    410         /** Paths of any split APKs, ordered by parsed splitName */
    411         public final String[] splitCodePaths;
    412 
    413         /** Revision code of base APK */
    414         public final int baseRevisionCode;
    415         /** Revision codes of any split APKs, ordered by parsed splitName */
    416         public final int[] splitRevisionCodes;
    417 
    418         public final boolean coreApp;
    419         public final boolean debuggable;
    420         public final boolean multiArch;
    421         public final boolean use32bitAbi;
    422         public final boolean extractNativeLibs;
    423         public final boolean isolatedSplits;
    424 
    425         public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
    426                 boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit,
    427                 String[] splitCodePaths, int[] splitRevisionCodes) {
    428             this.packageName = baseApk.packageName;
    429             this.versionCode = baseApk.versionCode;
    430             this.versionCodeMajor = baseApk.versionCodeMajor;
    431             this.installLocation = baseApk.installLocation;
    432             this.verifiers = baseApk.verifiers;
    433             this.splitNames = splitNames;
    434             this.isFeatureSplits = isFeatureSplits;
    435             this.usesSplitNames = usesSplitNames;
    436             this.configForSplit = configForSplit;
    437             this.codePath = codePath;
    438             this.baseCodePath = baseApk.codePath;
    439             this.splitCodePaths = splitCodePaths;
    440             this.baseRevisionCode = baseApk.revisionCode;
    441             this.splitRevisionCodes = splitRevisionCodes;
    442             this.coreApp = baseApk.coreApp;
    443             this.debuggable = baseApk.debuggable;
    444             this.multiArch = baseApk.multiArch;
    445             this.use32bitAbi = baseApk.use32bitAbi;
    446             this.extractNativeLibs = baseApk.extractNativeLibs;
    447             this.isolatedSplits = baseApk.isolatedSplits;
    448         }
    449 
    450         public List<String> getAllCodePaths() {
    451             ArrayList<String> paths = new ArrayList<>();
    452             paths.add(baseCodePath);
    453             if (!ArrayUtils.isEmpty(splitCodePaths)) {
    454                 Collections.addAll(paths, splitCodePaths);
    455             }
    456             return paths;
    457         }
    458     }
    459 
    460     /**
    461      * Lightweight parsed details about a single APK file.
    462      */
    463     public static class ApkLite {
    464         public final String codePath;
    465         public final String packageName;
    466         public final String splitName;
    467         public boolean isFeatureSplit;
    468         public final String configForSplit;
    469         public final String usesSplitName;
    470         public final int versionCode;
    471         public final int versionCodeMajor;
    472         public final int revisionCode;
    473         public final int installLocation;
    474         public final VerifierInfo[] verifiers;
    475         public final SigningDetails signingDetails;
    476         public final boolean coreApp;
    477         public final boolean debuggable;
    478         public final boolean multiArch;
    479         public final boolean use32bitAbi;
    480         public final boolean extractNativeLibs;
    481         public final boolean isolatedSplits;
    482 
    483         public ApkLite(String codePath, String packageName, String splitName,
    484                 boolean isFeatureSplit,
    485                 String configForSplit, String usesSplitName, int versionCode, int versionCodeMajor,
    486                 int revisionCode, int installLocation, List<VerifierInfo> verifiers,
    487                 SigningDetails signingDetails, boolean coreApp,
    488                 boolean debuggable, boolean multiArch, boolean use32bitAbi,
    489                 boolean extractNativeLibs, boolean isolatedSplits) {
    490             this.codePath = codePath;
    491             this.packageName = packageName;
    492             this.splitName = splitName;
    493             this.isFeatureSplit = isFeatureSplit;
    494             this.configForSplit = configForSplit;
    495             this.usesSplitName = usesSplitName;
    496             this.versionCode = versionCode;
    497             this.versionCodeMajor = versionCodeMajor;
    498             this.revisionCode = revisionCode;
    499             this.installLocation = installLocation;
    500             this.signingDetails = signingDetails;
    501             this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
    502             this.coreApp = coreApp;
    503             this.debuggable = debuggable;
    504             this.multiArch = multiArch;
    505             this.use32bitAbi = use32bitAbi;
    506             this.extractNativeLibs = extractNativeLibs;
    507             this.isolatedSplits = isolatedSplits;
    508         }
    509 
    510         public long getLongVersionCode() {
    511             return PackageInfo.composeLongVersionCode(versionCodeMajor, versionCode);
    512         }
    513     }
    514 
    515     /**
    516      * Cached parse state for new components.
    517      *
    518      * Allows reuse of the same parse argument records to avoid GC pressure.  Lifetime is carefully
    519      * scoped to the parsing of a single application element.
    520      */
    521     private static class CachedComponentArgs {
    522         ParseComponentArgs mActivityArgs;
    523         ParseComponentArgs mActivityAliasArgs;
    524         ParseComponentArgs mServiceArgs;
    525         ParseComponentArgs mProviderArgs;
    526     }
    527 
    528     /**
    529      * Cached state for parsing instrumentation to avoid GC pressure.
    530      *
    531      * Must be manually reset to null for each new manifest.
    532      */
    533     private ParsePackageItemArgs mParseInstrumentationArgs;
    534 
    535     /** If set to true, we will only allow package files that exactly match
    536      *  the DTD.  Otherwise, we try to get as much from the package as we
    537      *  can without failing.  This should normally be set to false, to
    538      *  support extensions to the DTD in future versions. */
    539     private static final boolean RIGID_PARSER = false;
    540 
    541     private static final String TAG = "PackageParser";
    542 
    543     public PackageParser() {
    544         mMetrics = new DisplayMetrics();
    545         mMetrics.setToDefaults();
    546     }
    547 
    548     public void setSeparateProcesses(String[] procs) {
    549         mSeparateProcesses = procs;
    550     }
    551 
    552     /**
    553      * Flag indicating this parser should only consider apps with
    554      * {@code coreApp} manifest attribute to be valid apps. This is useful when
    555      * creating a minimalist boot environment.
    556      */
    557     public void setOnlyCoreApps(boolean onlyCoreApps) {
    558         mOnlyCoreApps = onlyCoreApps;
    559     }
    560 
    561     public void setDisplayMetrics(DisplayMetrics metrics) {
    562         mMetrics = metrics;
    563     }
    564 
    565     /**
    566      * Sets the cache directory for this package parser.
    567      */
    568     public void setCacheDir(File cacheDir) {
    569         mCacheDir = cacheDir;
    570     }
    571 
    572     /**
    573      * Callback interface for retrieving information that may be needed while parsing
    574      * a package.
    575      */
    576     public interface Callback {
    577         boolean hasFeature(String feature);
    578         String[] getOverlayPaths(String targetPackageName, String targetPath);
    579         String[] getOverlayApks(String targetPackageName);
    580     }
    581 
    582     /**
    583      * Standard implementation of {@link Callback} on top of the public {@link PackageManager}
    584      * class.
    585      */
    586     public static final class CallbackImpl implements Callback {
    587         private final PackageManager mPm;
    588 
    589         public CallbackImpl(PackageManager pm) {
    590             mPm = pm;
    591         }
    592 
    593         @Override public boolean hasFeature(String feature) {
    594             return mPm.hasSystemFeature(feature);
    595         }
    596 
    597         @Override public String[] getOverlayPaths(String targetPackageName, String targetPath) {
    598             return null;
    599         }
    600 
    601         @Override public String[] getOverlayApks(String targetPackageName) {
    602             return null;
    603         }
    604     }
    605 
    606     /**
    607      * Set the {@link Callback} that can be used while parsing.
    608      */
    609     public void setCallback(Callback cb) {
    610         mCallback = cb;
    611     }
    612 
    613     public static final boolean isApkFile(File file) {
    614         return isApkPath(file.getName());
    615     }
    616 
    617     public static boolean isApkPath(String path) {
    618         return path.endsWith(APK_FILE_EXTENSION);
    619     }
    620 
    621     /**
    622      * Generate and return the {@link PackageInfo} for a parsed package.
    623      *
    624      * @param p the parsed package.
    625      * @param flags indicating which optional information is included.
    626      */
    627     public static PackageInfo generatePackageInfo(PackageParser.Package p,
    628             int gids[], int flags, long firstInstallTime, long lastUpdateTime,
    629             Set<String> grantedPermissions, PackageUserState state) {
    630 
    631         return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
    632                 grantedPermissions, state, UserHandle.getCallingUserId());
    633     }
    634 
    635     /**
    636      * Returns true if the package is installed and not hidden, or if the caller
    637      * explicitly wanted all uninstalled and hidden packages as well.
    638      * @param appInfo The applicationInfo of the app being checked.
    639      */
    640     private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state,
    641             ApplicationInfo appInfo) {
    642         // If available for the target user, or trying to match uninstalled packages and it's
    643         // a system app.
    644         return state.isAvailable(flags)
    645                 || (appInfo != null && appInfo.isSystemApp()
    646                         && (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0);
    647     }
    648 
    649     public static boolean isAvailable(PackageUserState state) {
    650         return checkUseInstalledOrHidden(0, state, null);
    651     }
    652 
    653     public static PackageInfo generatePackageInfo(PackageParser.Package p,
    654             int gids[], int flags, long firstInstallTime, long lastUpdateTime,
    655             Set<String> grantedPermissions, PackageUserState state, int userId) {
    656         if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
    657             return null;
    658         }
    659         PackageInfo pi = new PackageInfo();
    660         pi.packageName = p.packageName;
    661         pi.splitNames = p.splitNames;
    662         pi.versionCode = p.mVersionCode;
    663         pi.versionCodeMajor = p.mVersionCodeMajor;
    664         pi.baseRevisionCode = p.baseRevisionCode;
    665         pi.splitRevisionCodes = p.splitRevisionCodes;
    666         pi.versionName = p.mVersionName;
    667         pi.sharedUserId = p.mSharedUserId;
    668         pi.sharedUserLabel = p.mSharedUserLabel;
    669         pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
    670         pi.installLocation = p.installLocation;
    671         pi.isStub = p.isStub;
    672         pi.coreApp = p.coreApp;
    673         if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
    674                 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
    675             pi.requiredForAllUsers = p.mRequiredForAllUsers;
    676         }
    677         pi.restrictedAccountType = p.mRestrictedAccountType;
    678         pi.requiredAccountType = p.mRequiredAccountType;
    679         pi.overlayTarget = p.mOverlayTarget;
    680         pi.overlayCategory = p.mOverlayCategory;
    681         pi.overlayPriority = p.mOverlayPriority;
    682         pi.mOverlayIsStatic = p.mOverlayIsStatic;
    683         pi.compileSdkVersion = p.mCompileSdkVersion;
    684         pi.compileSdkVersionCodename = p.mCompileSdkVersionCodename;
    685         pi.firstInstallTime = firstInstallTime;
    686         pi.lastUpdateTime = lastUpdateTime;
    687         if ((flags&PackageManager.GET_GIDS) != 0) {
    688             pi.gids = gids;
    689         }
    690         if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
    691             int N = p.configPreferences != null ? p.configPreferences.size() : 0;
    692             if (N > 0) {
    693                 pi.configPreferences = new ConfigurationInfo[N];
    694                 p.configPreferences.toArray(pi.configPreferences);
    695             }
    696             N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
    697             if (N > 0) {
    698                 pi.reqFeatures = new FeatureInfo[N];
    699                 p.reqFeatures.toArray(pi.reqFeatures);
    700             }
    701             N = p.featureGroups != null ? p.featureGroups.size() : 0;
    702             if (N > 0) {
    703                 pi.featureGroups = new FeatureGroupInfo[N];
    704                 p.featureGroups.toArray(pi.featureGroups);
    705             }
    706         }
    707         if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
    708             final int N = p.activities.size();
    709             if (N > 0) {
    710                 int num = 0;
    711                 final ActivityInfo[] res = new ActivityInfo[N];
    712                 for (int i = 0; i < N; i++) {
    713                     final Activity a = p.activities.get(i);
    714                     if (state.isMatch(a.info, flags)) {
    715                         res[num++] = generateActivityInfo(a, flags, state, userId);
    716                     }
    717                 }
    718                 pi.activities = ArrayUtils.trimToSize(res, num);
    719             }
    720         }
    721         if ((flags & PackageManager.GET_RECEIVERS) != 0) {
    722             final int N = p.receivers.size();
    723             if (N > 0) {
    724                 int num = 0;
    725                 final ActivityInfo[] res = new ActivityInfo[N];
    726                 for (int i = 0; i < N; i++) {
    727                     final Activity a = p.receivers.get(i);
    728                     if (state.isMatch(a.info, flags)) {
    729                         res[num++] = generateActivityInfo(a, flags, state, userId);
    730                     }
    731                 }
    732                 pi.receivers = ArrayUtils.trimToSize(res, num);
    733             }
    734         }
    735         if ((flags & PackageManager.GET_SERVICES) != 0) {
    736             final int N = p.services.size();
    737             if (N > 0) {
    738                 int num = 0;
    739                 final ServiceInfo[] res = new ServiceInfo[N];
    740                 for (int i = 0; i < N; i++) {
    741                     final Service s = p.services.get(i);
    742                     if (state.isMatch(s.info, flags)) {
    743                         res[num++] = generateServiceInfo(s, flags, state, userId);
    744                     }
    745                 }
    746                 pi.services = ArrayUtils.trimToSize(res, num);
    747             }
    748         }
    749         if ((flags & PackageManager.GET_PROVIDERS) != 0) {
    750             final int N = p.providers.size();
    751             if (N > 0) {
    752                 int num = 0;
    753                 final ProviderInfo[] res = new ProviderInfo[N];
    754                 for (int i = 0; i < N; i++) {
    755                     final Provider pr = p.providers.get(i);
    756                     if (state.isMatch(pr.info, flags)) {
    757                         res[num++] = generateProviderInfo(pr, flags, state, userId);
    758                     }
    759                 }
    760                 pi.providers = ArrayUtils.trimToSize(res, num);
    761             }
    762         }
    763         if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
    764             int N = p.instrumentation.size();
    765             if (N > 0) {
    766                 pi.instrumentation = new InstrumentationInfo[N];
    767                 for (int i=0; i<N; i++) {
    768                     pi.instrumentation[i] = generateInstrumentationInfo(
    769                             p.instrumentation.get(i), flags);
    770                 }
    771             }
    772         }
    773         if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
    774             int N = p.permissions.size();
    775             if (N > 0) {
    776                 pi.permissions = new PermissionInfo[N];
    777                 for (int i=0; i<N; i++) {
    778                     pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
    779                 }
    780             }
    781             N = p.requestedPermissions.size();
    782             if (N > 0) {
    783                 pi.requestedPermissions = new String[N];
    784                 pi.requestedPermissionsFlags = new int[N];
    785                 for (int i=0; i<N; i++) {
    786                     final String perm = p.requestedPermissions.get(i);
    787                     pi.requestedPermissions[i] = perm;
    788                     // The notion of required permissions is deprecated but for compatibility.
    789                     pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
    790                     if (grantedPermissions != null && grantedPermissions.contains(perm)) {
    791                         pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
    792                     }
    793                 }
    794             }
    795         }
    796         // deprecated method of getting signing certificates
    797         if ((flags&PackageManager.GET_SIGNATURES) != 0) {
    798             if (p.mSigningDetails.hasPastSigningCertificates()) {
    799                 // Package has included signing certificate rotation information.  Return the oldest
    800                 // cert so that programmatic checks keep working even if unaware of key rotation.
    801                 pi.signatures = new Signature[1];
    802                 pi.signatures[0] = p.mSigningDetails.pastSigningCertificates[0];
    803             } else if (p.mSigningDetails.hasSignatures()) {
    804                 // otherwise keep old behavior
    805                 int numberOfSigs = p.mSigningDetails.signatures.length;
    806                 pi.signatures = new Signature[numberOfSigs];
    807                 System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs);
    808             }
    809         }
    810 
    811         // replacement for GET_SIGNATURES
    812         if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
    813             if (p.mSigningDetails != SigningDetails.UNKNOWN) {
    814                 // only return a valid SigningInfo if there is signing information to report
    815                 pi.signingInfo = new SigningInfo(p.mSigningDetails);
    816             } else {
    817                 pi.signingInfo = null;
    818             }
    819         }
    820         return pi;
    821     }
    822 
    823     public static final int PARSE_MUST_BE_APK = 1 << 0;
    824     public static final int PARSE_IGNORE_PROCESSES = 1 << 1;
    825     /** @deprecated forward lock no longer functional. remove. */
    826     @Deprecated
    827     public static final int PARSE_FORWARD_LOCK = 1 << 2;
    828     public static final int PARSE_EXTERNAL_STORAGE = 1 << 3;
    829     public static final int PARSE_IS_SYSTEM_DIR = 1 << 4;
    830     public static final int PARSE_COLLECT_CERTIFICATES = 1 << 5;
    831     public static final int PARSE_ENFORCE_CODE = 1 << 6;
    832     public static final int PARSE_FORCE_SDK = 1 << 7;
    833     public static final int PARSE_CHATTY = 1 << 31;
    834 
    835     @IntDef(flag = true, prefix = { "PARSE_" }, value = {
    836             PARSE_CHATTY,
    837             PARSE_COLLECT_CERTIFICATES,
    838             PARSE_ENFORCE_CODE,
    839             PARSE_EXTERNAL_STORAGE,
    840             PARSE_FORCE_SDK,
    841             PARSE_FORWARD_LOCK,
    842             PARSE_IGNORE_PROCESSES,
    843             PARSE_IS_SYSTEM_DIR,
    844             PARSE_MUST_BE_APK,
    845     })
    846     @Retention(RetentionPolicy.SOURCE)
    847     public @interface ParseFlags {}
    848 
    849     private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
    850 
    851     /**
    852      * Used to sort a set of APKs based on their split names, always placing the
    853      * base APK (with {@code null} split name) first.
    854      */
    855     private static class SplitNameComparator implements Comparator<String> {
    856         @Override
    857         public int compare(String lhs, String rhs) {
    858             if (lhs == null) {
    859                 return -1;
    860             } else if (rhs == null) {
    861                 return 1;
    862             } else {
    863                 return lhs.compareTo(rhs);
    864             }
    865         }
    866     }
    867 
    868     /**
    869      * Parse only lightweight details about the package at the given location.
    870      * Automatically detects if the package is a monolithic style (single APK
    871      * file) or cluster style (directory of APKs).
    872      * <p>
    873      * This performs sanity checking on cluster style packages, such as
    874      * requiring identical package name and version codes, a single base APK,
    875      * and unique split names.
    876      *
    877      * @see PackageParser#parsePackage(File, int)
    878      */
    879     public static PackageLite parsePackageLite(File packageFile, int flags)
    880             throws PackageParserException {
    881         if (packageFile.isDirectory()) {
    882             return parseClusterPackageLite(packageFile, flags);
    883         } else {
    884             return parseMonolithicPackageLite(packageFile, flags);
    885         }
    886     }
    887 
    888     private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
    889             throws PackageParserException {
    890         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
    891         final ApkLite baseApk = parseApkLite(packageFile, flags);
    892         final String packagePath = packageFile.getAbsolutePath();
    893         Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    894         return new PackageLite(packagePath, baseApk, null, null, null, null, null, null);
    895     }
    896 
    897     static PackageLite parseClusterPackageLite(File packageDir, int flags)
    898             throws PackageParserException {
    899         final File[] files = packageDir.listFiles();
    900         if (ArrayUtils.isEmpty(files)) {
    901             throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
    902                     "No packages found in split");
    903         }
    904 
    905         String packageName = null;
    906         int versionCode = 0;
    907 
    908         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
    909         final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
    910         for (File file : files) {
    911             if (isApkFile(file)) {
    912                 final ApkLite lite = parseApkLite(file, flags);
    913 
    914                 // Assert that all package names and version codes are
    915                 // consistent with the first one we encounter.
    916                 if (packageName == null) {
    917                     packageName = lite.packageName;
    918                     versionCode = lite.versionCode;
    919                 } else {
    920                     if (!packageName.equals(lite.packageName)) {
    921                         throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
    922                                 "Inconsistent package " + lite.packageName + " in " + file
    923                                 + "; expected " + packageName);
    924                     }
    925                     if (versionCode != lite.versionCode) {
    926                         throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
    927                                 "Inconsistent version " + lite.versionCode + " in " + file
    928                                 + "; expected " + versionCode);
    929                     }
    930                 }
    931 
    932                 // Assert that each split is defined only once
    933                 if (apks.put(lite.splitName, lite) != null) {
    934                     throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
    935                             "Split name " + lite.splitName
    936                             + " defined more than once; most recent was " + file);
    937                 }
    938             }
    939         }
    940         Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    941 
    942         final ApkLite baseApk = apks.remove(null);
    943         if (baseApk == null) {
    944             throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
    945                     "Missing base APK in " + packageDir);
    946         }
    947 
    948         // Always apply deterministic ordering based on splitName
    949         final int size = apks.size();
    950 
    951         String[] splitNames = null;
    952         boolean[] isFeatureSplits = null;
    953         String[] usesSplitNames = null;
    954         String[] configForSplits = null;
    955         String[] splitCodePaths = null;
    956         int[] splitRevisionCodes = null;
    957         String[] splitClassLoaderNames = null;
    958         if (size > 0) {
    959             splitNames = new String[size];
    960             isFeatureSplits = new boolean[size];
    961             usesSplitNames = new String[size];
    962             configForSplits = new String[size];
    963             splitCodePaths = new String[size];
    964             splitRevisionCodes = new int[size];
    965 
    966             splitNames = apks.keySet().toArray(splitNames);
    967             Arrays.sort(splitNames, sSplitNameComparator);
    968 
    969             for (int i = 0; i < size; i++) {
    970                 final ApkLite apk = apks.get(splitNames[i]);
    971                 usesSplitNames[i] = apk.usesSplitName;
    972                 isFeatureSplits[i] = apk.isFeatureSplit;
    973                 configForSplits[i] = apk.configForSplit;
    974                 splitCodePaths[i] = apk.codePath;
    975                 splitRevisionCodes[i] = apk.revisionCode;
    976             }
    977         }
    978 
    979         final String codePath = packageDir.getAbsolutePath();
    980         return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames,
    981                 configForSplits, splitCodePaths, splitRevisionCodes);
    982     }
    983 
    984     /**
    985      * Parse the package at the given location. Automatically detects if the
    986      * package is a monolithic style (single APK file) or cluster style
    987      * (directory of APKs).
    988      * <p>
    989      * This performs sanity checking on cluster style packages, such as
    990      * requiring identical package name and version codes, a single base APK,
    991      * and unique split names.
    992      * <p>
    993      * Note that this <em>does not</em> perform signature verification; that
    994      * must be done separately in {@link #collectCertificates(Package, int)}.
    995      *
    996      * If {@code useCaches} is true, the package parser might return a cached
    997      * result from a previous parse of the same {@code packageFile} with the same
    998      * {@code flags}. Note that this method does not check whether {@code packageFile}
    999      * has changed since the last parse, it's up to callers to do so.
   1000      *
   1001      * @see #parsePackageLite(File, int)
   1002      */
   1003     public Package parsePackage(File packageFile, int flags, boolean useCaches)
   1004             throws PackageParserException {
   1005         Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
   1006         if (parsed != null) {
   1007             return parsed;
   1008         }
   1009 
   1010         long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
   1011         if (packageFile.isDirectory()) {
   1012             parsed = parseClusterPackage(packageFile, flags);
   1013         } else {
   1014             parsed = parseMonolithicPackage(packageFile, flags);
   1015         }
   1016 
   1017         long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
   1018         cacheResult(packageFile, flags, parsed);
   1019         if (LOG_PARSE_TIMINGS) {
   1020             parseTime = cacheTime - parseTime;
   1021             cacheTime = SystemClock.uptimeMillis() - cacheTime;
   1022             if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) {
   1023                 Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime
   1024                         + "ms, update_cache=" + cacheTime + " ms");
   1025             }
   1026         }
   1027         return parsed;
   1028     }
   1029 
   1030     /**
   1031      * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}.
   1032      */
   1033     public Package parsePackage(File packageFile, int flags) throws PackageParserException {
   1034         return parsePackage(packageFile, flags, false /* useCaches */);
   1035     }
   1036 
   1037     /**
   1038      * Returns the cache key for a specificied {@code packageFile} and {@code flags}.
   1039      */
   1040     private String getCacheKey(File packageFile, int flags) {
   1041         StringBuilder sb = new StringBuilder(packageFile.getName());
   1042         sb.append('-');
   1043         sb.append(flags);
   1044 
   1045         return sb.toString();
   1046     }
   1047 
   1048     @VisibleForTesting
   1049     protected Package fromCacheEntry(byte[] bytes) {
   1050         return fromCacheEntryStatic(bytes);
   1051     }
   1052 
   1053     /** static version of {@link #fromCacheEntry} for unit tests. */
   1054     @VisibleForTesting
   1055     public static Package fromCacheEntryStatic(byte[] bytes) {
   1056         final Parcel p = Parcel.obtain();
   1057         p.unmarshall(bytes, 0, bytes.length);
   1058         p.setDataPosition(0);
   1059 
   1060         final ReadHelper helper = new ReadHelper(p);
   1061         helper.startAndInstall();
   1062 
   1063         PackageParser.Package pkg = new PackageParser.Package(p);
   1064 
   1065         p.recycle();
   1066 
   1067         sCachedPackageReadCount.incrementAndGet();
   1068 
   1069         return pkg;
   1070     }
   1071 
   1072     @VisibleForTesting
   1073     protected byte[] toCacheEntry(Package pkg) {
   1074         return toCacheEntryStatic(pkg);
   1075 
   1076     }
   1077 
   1078     /** static version of {@link #toCacheEntry} for unit tests. */
   1079     @VisibleForTesting
   1080     public static byte[] toCacheEntryStatic(Package pkg) {
   1081         final Parcel p = Parcel.obtain();
   1082         final WriteHelper helper = new WriteHelper(p);
   1083 
   1084         pkg.writeToParcel(p, 0 /* flags */);
   1085 
   1086         helper.finishAndUninstall();
   1087 
   1088         byte[] serialized = p.marshall();
   1089         p.recycle();
   1090 
   1091         return serialized;
   1092     }
   1093 
   1094     /**
   1095      * Given a {@code packageFile} and a {@code cacheFile} returns whether the
   1096      * cache file is up to date based on the mod-time of both files.
   1097      */
   1098     private static boolean isCacheUpToDate(File packageFile, File cacheFile) {
   1099         try {
   1100             // NOTE: We don't use the File.lastModified API because it has the very
   1101             // non-ideal failure mode of returning 0 with no excepions thrown.
   1102             // The nio2 Files API is a little better but is considerably more expensive.
   1103             final StructStat pkg = android.system.Os.stat(packageFile.getAbsolutePath());
   1104             final StructStat cache = android.system.Os.stat(cacheFile.getAbsolutePath());
   1105             return pkg.st_mtime < cache.st_mtime;
   1106         } catch (ErrnoException ee) {
   1107             // The most common reason why stat fails is that a given cache file doesn't
   1108             // exist. We ignore that here. It's easy to reason that it's safe to say the
   1109             // cache isn't up to date if we see any sort of exception here.
   1110             //
   1111             // (1) Exception while stating the package file : This should never happen,
   1112             // and if it does, we do a full package parse (which is likely to throw the
   1113             // same exception).
   1114             // (2) Exception while stating the cache file : If the file doesn't exist, the
   1115             // cache is obviously out of date. If the file *does* exist, we can't read it.
   1116             // We will attempt to delete and recreate it after parsing the package.
   1117             if (ee.errno != OsConstants.ENOENT) {
   1118                 Slog.w("Error while stating package cache : ", ee);
   1119             }
   1120 
   1121             return false;
   1122         }
   1123     }
   1124 
   1125     /**
   1126      * Returns the cached parse result for {@code packageFile} for parse flags {@code flags},
   1127      * or {@code null} if no cached result exists.
   1128      */
   1129     private Package getCachedResult(File packageFile, int flags) {
   1130         if (mCacheDir == null) {
   1131             return null;
   1132         }
   1133 
   1134         final String cacheKey = getCacheKey(packageFile, flags);
   1135         final File cacheFile = new File(mCacheDir, cacheKey);
   1136 
   1137         try {
   1138             // If the cache is not up to date, return null.
   1139             if (!isCacheUpToDate(packageFile, cacheFile)) {
   1140                 return null;
   1141             }
   1142 
   1143             final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
   1144             Package p = fromCacheEntry(bytes);
   1145             if (mCallback != null) {
   1146                 String[] overlayApks = mCallback.getOverlayApks(p.packageName);
   1147                 if (overlayApks != null && overlayApks.length > 0) {
   1148                     for (String overlayApk : overlayApks) {
   1149                         // If a static RRO is updated, return null.
   1150                         if (!isCacheUpToDate(new File(overlayApk), cacheFile)) {
   1151                             return null;
   1152                         }
   1153                     }
   1154                 }
   1155             }
   1156             return p;
   1157         } catch (Throwable e) {
   1158             Slog.w(TAG, "Error reading package cache: ", e);
   1159 
   1160             // If something went wrong while reading the cache entry, delete the cache file
   1161             // so that we regenerate it the next time.
   1162             cacheFile.delete();
   1163             return null;
   1164         }
   1165     }
   1166 
   1167     /**
   1168      * Caches the parse result for {@code packageFile} with flags {@code flags}.
   1169      */
   1170     private void cacheResult(File packageFile, int flags, Package parsed) {
   1171         if (mCacheDir == null) {
   1172             return;
   1173         }
   1174 
   1175         try {
   1176             final String cacheKey = getCacheKey(packageFile, flags);
   1177             final File cacheFile = new File(mCacheDir, cacheKey);
   1178 
   1179             if (cacheFile.exists()) {
   1180                 if (!cacheFile.delete()) {
   1181                     Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
   1182                 }
   1183             }
   1184 
   1185             final byte[] cacheEntry = toCacheEntry(parsed);
   1186 
   1187             if (cacheEntry == null) {
   1188                 return;
   1189             }
   1190 
   1191             try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
   1192                 fos.write(cacheEntry);
   1193             } catch (IOException ioe) {
   1194                 Slog.w(TAG, "Error writing cache entry.", ioe);
   1195                 cacheFile.delete();
   1196             }
   1197         } catch (Throwable e) {
   1198             Slog.w(TAG, "Error saving package cache.", e);
   1199         }
   1200     }
   1201 
   1202     /**
   1203      * Parse all APKs contained in the given directory, treating them as a
   1204      * single package. This also performs sanity checking, such as requiring
   1205      * identical package name and version codes, a single base APK, and unique
   1206      * split names.
   1207      * <p>
   1208      * Note that this <em>does not</em> perform signature verification; that
   1209      * must be done separately in {@link #collectCertificates(Package, int)}.
   1210      */
   1211     private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
   1212         final PackageLite lite = parseClusterPackageLite(packageDir, 0);
   1213         if (mOnlyCoreApps && !lite.coreApp) {
   1214             throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
   1215                     "Not a coreApp: " + packageDir);
   1216         }
   1217 
   1218         // Build the split dependency tree.
   1219         SparseArray<int[]> splitDependencies = null;
   1220         final SplitAssetLoader assetLoader;
   1221         if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) {
   1222             try {
   1223                 splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite);
   1224                 assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags);
   1225             } catch (SplitAssetDependencyLoader.IllegalDependencyException e) {
   1226                 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage());
   1227             }
   1228         } else {
   1229             assetLoader = new DefaultSplitAssetLoader(lite, flags);
   1230         }
   1231 
   1232         try {
   1233             final AssetManager assets = assetLoader.getBaseAssetManager();
   1234             final File baseApk = new File(lite.baseCodePath);
   1235             final Package pkg = parseBaseApk(baseApk, assets, flags);
   1236             if (pkg == null) {
   1237                 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
   1238                         "Failed to parse base APK: " + baseApk);
   1239             }
   1240 
   1241             if (!ArrayUtils.isEmpty(lite.splitNames)) {
   1242                 final int num = lite.splitNames.length;
   1243                 pkg.splitNames = lite.splitNames;
   1244                 pkg.splitCodePaths = lite.splitCodePaths;
   1245                 pkg.splitRevisionCodes = lite.splitRevisionCodes;
   1246                 pkg.splitFlags = new int[num];
   1247                 pkg.splitPrivateFlags = new int[num];
   1248                 pkg.applicationInfo.splitNames = pkg.splitNames;
   1249                 pkg.applicationInfo.splitDependencies = splitDependencies;
   1250                 pkg.applicationInfo.splitClassLoaderNames = new String[num];
   1251 
   1252                 for (int i = 0; i < num; i++) {
   1253                     final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
   1254                     parseSplitApk(pkg, i, splitAssets, flags);
   1255                 }
   1256             }
   1257 
   1258             pkg.setCodePath(packageDir.getCanonicalPath());
   1259             pkg.setUse32bitAbi(lite.use32bitAbi);
   1260             return pkg;
   1261         } catch (IOException e) {
   1262             throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
   1263                     "Failed to get path: " + lite.baseCodePath, e);
   1264         } finally {
   1265             IoUtils.closeQuietly(assetLoader);
   1266         }
   1267     }
   1268 
   1269     /**
   1270      * Parse the given APK file, treating it as as a single monolithic package.
   1271      * <p>
   1272      * Note that this <em>does not</em> perform signature verification; that
   1273      * must be done separately in {@link #collectCertificates(Package, int)}.
   1274      *
   1275      * @deprecated external callers should move to
   1276      *             {@link #parsePackage(File, int)}. Eventually this method will
   1277      *             be marked private.
   1278      */
   1279     @Deprecated
   1280     public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
   1281         final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
   1282         if (mOnlyCoreApps) {
   1283             if (!lite.coreApp) {
   1284                 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
   1285                         "Not a coreApp: " + apkFile);
   1286             }
   1287         }
   1288 
   1289         final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
   1290         try {
   1291             final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags);
   1292             pkg.setCodePath(apkFile.getCanonicalPath());
   1293             pkg.setUse32bitAbi(lite.use32bitAbi);
   1294             return pkg;
   1295         } catch (IOException e) {
   1296             throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
   1297                     "Failed to get path: " + apkFile, e);
   1298         } finally {
   1299             IoUtils.closeQuietly(assetLoader);
   1300         }
   1301     }
   1302 
   1303     private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
   1304             throws PackageParserException {
   1305         final String apkPath = apkFile.getAbsolutePath();
   1306 
   1307         String volumeUuid = null;
   1308         if (apkPath.startsWith(MNT_EXPAND)) {
   1309             final int end = apkPath.indexOf('/', MNT_EXPAND.length());
   1310             volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
   1311         }
   1312 
   1313         mParseError = PackageManager.INSTALL_SUCCEEDED;
   1314         mArchiveSourcePath = apkFile.getAbsolutePath();
   1315 
   1316         if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
   1317 
   1318         XmlResourceParser parser = null;
   1319         try {
   1320             final int cookie = assets.findCookieForPath(apkPath);
   1321             if (cookie == 0) {
   1322                 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
   1323                         "Failed adding asset path: " + apkPath);
   1324             }
   1325             parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
   1326             final Resources res = new Resources(assets, mMetrics, null);
   1327 
   1328             final String[] outError = new String[1];
   1329             final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
   1330             if (pkg == null) {
   1331                 throw new PackageParserException(mParseError,
   1332                         apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
   1333             }
   1334 
   1335             pkg.setVolumeUuid(volumeUuid);
   1336             pkg.setApplicationVolumeUuid(volumeUuid);
   1337             pkg.setBaseCodePath(apkPath);
   1338             pkg.setSigningDetails(SigningDetails.UNKNOWN);
   1339 
   1340             return pkg;
   1341 
   1342         } catch (PackageParserException e) {
   1343             throw e;
   1344         } catch (Exception e) {
   1345             throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
   1346                     "Failed to read manifest from " + apkPath, e);
   1347         } finally {
   1348             IoUtils.closeQuietly(parser);
   1349         }
   1350     }
   1351 
   1352     private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
   1353             throws PackageParserException {
   1354         final String apkPath = pkg.splitCodePaths[splitIndex];
   1355 
   1356         mParseError = PackageManager.INSTALL_SUCCEEDED;
   1357         mArchiveSourcePath = apkPath;
   1358 
   1359         if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
   1360 
   1361         final Resources res;
   1362         XmlResourceParser parser = null;
   1363         try {
   1364             // This must always succeed, as the path has been added to the AssetManager before.
   1365             final int cookie = assets.findCookieForPath(apkPath);
   1366             if (cookie == 0) {
   1367                 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
   1368                         "Failed adding asset path: " + apkPath);
   1369             }
   1370 
   1371             parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
   1372             res = new Resources(assets, mMetrics, null);
   1373 
   1374             final String[] outError = new String[1];
   1375             pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
   1376             if (pkg == null) {
   1377                 throw new PackageParserException(mParseError,
   1378                         apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
   1379             }
   1380 
   1381         } catch (PackageParserException e) {
   1382             throw e;
   1383         } catch (Exception e) {
   1384             throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
   1385                     "Failed to read manifest from " + apkPath, e);
   1386         } finally {
   1387             IoUtils.closeQuietly(parser);
   1388         }
   1389     }
   1390 
   1391     /**
   1392      * Parse the manifest of a <em>split APK</em>.
   1393      * <p>
   1394      * Note that split APKs have many more restrictions on what they're capable
   1395      * of doing, so many valid features of a base APK have been carefully
   1396      * omitted here.
   1397      */
   1398     private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
   1399             int splitIndex, String[] outError) throws XmlPullParserException, IOException,
   1400             PackageParserException {
   1401         AttributeSet attrs = parser;
   1402 
   1403         // We parsed manifest tag earlier; just skip past it
   1404         parsePackageSplitNames(parser, attrs);
   1405 
   1406         mParseInstrumentationArgs = null;
   1407 
   1408         int type;
   1409 
   1410         boolean foundApp = false;
   1411 
   1412         int outerDepth = parser.getDepth();
   1413         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
   1414                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
   1415             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   1416                 continue;
   1417             }
   1418 
   1419             String tagName = parser.getName();
   1420             if (tagName.equals(TAG_APPLICATION)) {
   1421                 if (foundApp) {
   1422                     if (RIGID_PARSER) {
   1423                         outError[0] = "<manifest> has more than one <application>";
   1424                         mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   1425                         return null;
   1426                     } else {
   1427                         Slog.w(TAG, "<manifest> has more than one <application>");
   1428                         XmlUtils.skipCurrentTag(parser);
   1429                         continue;
   1430                     }
   1431                 }
   1432 
   1433                 foundApp = true;
   1434                 if (!parseSplitApplication(pkg, res, parser, flags, splitIndex, outError)) {
   1435                     return null;
   1436                 }
   1437 
   1438             } else if (RIGID_PARSER) {
   1439                 outError[0] = "Bad element under <manifest>: "
   1440                     + parser.getName();
   1441                 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   1442                 return null;
   1443 
   1444             } else {
   1445                 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
   1446                         + " at " + mArchiveSourcePath + " "
   1447                         + parser.getPositionDescription());
   1448                 XmlUtils.skipCurrentTag(parser);
   1449                 continue;
   1450             }
   1451         }
   1452 
   1453         if (!foundApp) {
   1454             outError[0] = "<manifest> does not contain an <application>";
   1455             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
   1456         }
   1457 
   1458         return pkg;
   1459     }
   1460 
   1461     /** Parses the public keys from the set of signatures. */
   1462     public static ArraySet<PublicKey> toSigningKeys(Signature[] signatures)
   1463             throws CertificateException {
   1464         ArraySet<PublicKey> keys = new ArraySet<>(signatures.length);
   1465         for (int i = 0; i < signatures.length; i++) {
   1466             keys.add(signatures[i].getPublicKey());
   1467         }
   1468         return keys;
   1469     }
   1470 
   1471     /**
   1472      * Collect certificates from all the APKs described in the given package,
   1473      * populating {@link Package#mSigningDetails}. Also asserts that all APK
   1474      * contents are signed correctly and consistently.
   1475      */
   1476     public static void collectCertificates(Package pkg, boolean skipVerify)
   1477             throws PackageParserException {
   1478         collectCertificatesInternal(pkg, skipVerify);
   1479         final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
   1480         for (int i = 0; i < childCount; i++) {
   1481             Package childPkg = pkg.childPackages.get(i);
   1482             childPkg.mSigningDetails = pkg.mSigningDetails;
   1483         }
   1484     }
   1485 
   1486     private static void collectCertificatesInternal(Package pkg, boolean skipVerify)
   1487             throws PackageParserException {
   1488         pkg.mSigningDetails = SigningDetails.UNKNOWN;
   1489 
   1490         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
   1491         try {
   1492             collectCertificates(pkg, new File(pkg.baseCodePath), skipVerify);
   1493 
   1494             if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
   1495                 for (int i = 0; i < pkg.splitCodePaths.length; i++) {
   1496                     collectCertificates(pkg, new File(pkg.splitCodePaths[i]), skipVerify);
   1497                 }
   1498             }
   1499         } finally {
   1500             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
   1501         }
   1502     }
   1503 
   1504     private static void collectCertificates(Package pkg, File apkFile, boolean skipVerify)
   1505             throws PackageParserException {
   1506         final String apkPath = apkFile.getAbsolutePath();
   1507 
   1508         int minSignatureScheme = SigningDetails.SignatureSchemeVersion.JAR;
   1509         if (pkg.applicationInfo.isStaticSharedLibrary()) {
   1510             // must use v2 signing scheme
   1511             minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2;
   1512         }
   1513         SigningDetails verified;
   1514         if (skipVerify) {
   1515             // systemDir APKs are already trusted, save time by not verifying
   1516             verified = ApkSignatureVerifier.plsCertsNoVerifyOnlyCerts(
   1517                         apkPath, minSignatureScheme);
   1518         } else {
   1519             verified = ApkSignatureVerifier.verify(apkPath, minSignatureScheme);
   1520         }
   1521 
   1522         // Verify that entries are signed consistently with the first pkg
   1523         // we encountered. Note that for splits, certificates may have
   1524         // already been populated during an earlier parse of a base APK.
   1525         if (pkg.mSigningDetails == SigningDetails.UNKNOWN) {
   1526             pkg.mSigningDetails = verified;
   1527         } else {
   1528             if (!Signature.areExactMatch(pkg.mSigningDetails.signatures, verified.signatures)) {
   1529                 throw new PackageParserException(
   1530                         INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
   1531                         apkPath + " has mismatched certificates");
   1532             }
   1533         }
   1534     }
   1535 
   1536     private static AssetManager newConfiguredAssetManager() {
   1537         AssetManager assetManager = new AssetManager();
   1538         assetManager.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   1539                 Build.VERSION.RESOURCES_SDK_INT);
   1540         return assetManager;
   1541     }
   1542 
   1543     /**
   1544      * Utility method that retrieves lightweight details about a single APK
   1545      * file, including package name, split name, and install location.
   1546      *
   1547      * @param apkFile path to a single APK
   1548      * @param flags optional parse flags, such as
   1549      *            {@link #PARSE_COLLECT_CERTIFICATES}
   1550      */
   1551     public static ApkLite parseApkLite(File apkFile, int flags)
   1552             throws PackageParserException {
   1553         return parseApkLiteInner(apkFile, null, null, flags);
   1554     }
   1555 
   1556     /**
   1557      * Utility method that retrieves lightweight details about a single APK
   1558      * file, including package name, split name, and install location.
   1559      *
   1560      * @param fd already open file descriptor of an apk file
   1561      * @param debugPathName arbitrary text name for this file, for debug output
   1562      * @param flags optional parse flags, such as
   1563      *            {@link #PARSE_COLLECT_CERTIFICATES}
   1564      */
   1565     public static ApkLite parseApkLite(FileDescriptor fd, String debugPathName, int flags)
   1566             throws PackageParserException {
   1567         return parseApkLiteInner(null, fd, debugPathName, flags);
   1568     }
   1569 
   1570     private static ApkLite parseApkLiteInner(File apkFile, FileDescriptor fd, String debugPathName,
   1571             int flags) throws PackageParserException {
   1572         final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();
   1573 
   1574         XmlResourceParser parser = null;
   1575         try {
   1576             final ApkAssets apkAssets;
   1577             try {
   1578                 apkAssets = fd != null
   1579                         ? ApkAssets.loadFromFd(fd, debugPathName, false, false)
   1580                         : ApkAssets.loadFromPath(apkPath);
   1581             } catch (IOException e) {
   1582                 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
   1583                         "Failed to parse " + apkPath);
   1584             }
   1585 
   1586             parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME);
   1587 
   1588             final SigningDetails signingDetails;
   1589             if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
   1590                 // TODO: factor signature related items out of Package object
   1591                 final Package tempPkg = new Package((String) null);
   1592                 final boolean skipVerify = (flags & PARSE_IS_SYSTEM_DIR) != 0;
   1593                 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
   1594                 try {
   1595                     collectCertificates(tempPkg, apkFile, skipVerify);
   1596                 } finally {
   1597                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
   1598                 }
   1599                 signingDetails = tempPkg.mSigningDetails;
   1600             } else {
   1601                 signingDetails = SigningDetails.UNKNOWN;
   1602             }
   1603 
   1604             final AttributeSet attrs = parser;
   1605             return parseApkLite(apkPath, parser, attrs, signingDetails);
   1606 
   1607         } catch (XmlPullParserException | IOException | RuntimeException e) {
   1608             Slog.w(TAG, "Failed to parse " + apkPath, e);
   1609             throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
   1610                     "Failed to parse " + apkPath, e);
   1611         } finally {
   1612             IoUtils.closeQuietly(parser);
   1613             // TODO(b/72056911): Implement and call close() on ApkAssets.
   1614         }
   1615     }
   1616 
   1617     private static String validateName(String name, boolean requireSeparator,
   1618             boolean requireFilename) {
   1619         final int N = name.length();
   1620         boolean hasSep = false;
   1621         boolean front = true;
   1622         for (int i=0; i<N; i++) {
   1623             final char c = name.charAt(i);
   1624             if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
   1625                 front = false;
   1626                 continue;
   1627             }
   1628             if (!front) {
   1629                 if ((c >= '0' && c <= '9') || c == '_') {
   1630                     continue;
   1631                 }
   1632             }
   1633             if (c == '.') {
   1634                 hasSep = true;
   1635                 front = true;
   1636                 continue;
   1637             }
   1638             return "bad character '" + c + "'";
   1639         }
   1640         if (requireFilename && !FileUtils.isValidExtFilename(name)) {
   1641             return "Invalid filename";
   1642         }
   1643         return hasSep || !requireSeparator
   1644                 ? null : "must have at least one '.' separator";
   1645     }
   1646 
   1647     private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
   1648             AttributeSet attrs) throws IOException, XmlPullParserException,
   1649             PackageParserException {
   1650 
   1651         int type;
   1652         while ((type = parser.next()) != XmlPullParser.START_TAG
   1653                 && type != XmlPullParser.END_DOCUMENT) {
   1654         }
   1655 
   1656         if (type != XmlPullParser.START_TAG) {
   1657             throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
   1658                     "No start tag found");
   1659         }
   1660         if (!parser.getName().equals(TAG_MANIFEST)) {
   1661             throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
   1662                     "No <manifest> tag");
   1663         }
   1664 
   1665         final String packageName = attrs.getAttributeValue(null, "package");
   1666         if (!"android".equals(packageName)) {
   1667             final String error = validateName(packageName, true, true);
   1668             if (error != null) {
   1669                 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
   1670                         "Invalid manifest package: " + error);
   1671             }
   1672         }
   1673 
   1674         String splitName = attrs.getAttributeValue(null, "split");
   1675         if (splitName != null) {
   1676             if (splitName.length() == 0) {
   1677                 splitName = null;
   1678             } else {
   1679                 final String error = validateName(splitName, false, false);
   1680                 if (error != null) {
   1681                     throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
   1682                             "Invalid manifest split: " + error);
   1683                 }
   1684             }
   1685         }
   1686 
   1687         return Pair.create(packageName.intern(),
   1688                 (splitName != null) ? splitName.intern() : splitName);
   1689     }
   1690 
   1691     private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,
   1692             SigningDetails signingDetails)
   1693             throws IOException, XmlPullParserException, PackageParserException {
   1694         final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
   1695 
   1696         int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
   1697         int versionCode = 0;
   1698         int versionCodeMajor = 0;
   1699         int revisionCode = 0;
   1700         boolean coreApp = false;
   1701         boolean debuggable = false;
   1702         boolean multiArch = false;
   1703         boolean use32bitAbi = false;
   1704         boolean extractNativeLibs = true;
   1705         boolean isolatedSplits = false;
   1706         boolean isFeatureSplit = false;
   1707         String configForSplit = null;
   1708         String usesSplitName = null;
   1709 
   1710         for (int i = 0; i < attrs.getAttributeCount(); i++) {
   1711             final String attr = attrs.getAttributeName(i);
   1712             if (attr.equals("installLocation")) {
   1713                 installLocation = attrs.getAttributeIntValue(i,
   1714                         PARSE_DEFAULT_INSTALL_LOCATION);
   1715             } else if (attr.equals("versionCode")) {
   1716                 versionCode = attrs.getAttributeIntValue(i, 0);
   1717             } else if (attr.equals("versionCodeMajor")) {
   1718                 versionCodeMajor = attrs.getAttributeIntValue(i, 0);
   1719             } else if (attr.equals("revisionCode")) {
   1720                 revisionCode = attrs.getAttributeIntValue(i, 0);
   1721             } else if (attr.equals("coreApp")) {
   1722                 coreApp = attrs.getAttributeBooleanValue(i, false);
   1723             } else if (attr.equals("isolatedSplits")) {
   1724                 isolatedSplits = attrs.getAttributeBooleanValue(i, false);
   1725             } else if (attr.equals("configForSplit")) {
   1726                 configForSplit = attrs.getAttributeValue(i);
   1727             } else if (attr.equals("isFeatureSplit")) {
   1728                 isFeatureSplit = attrs.getAttributeBooleanValue(i, false);
   1729             }
   1730         }
   1731 
   1732         // Only search the tree when the tag is directly below <manifest>
   1733         int type;
   1734         final int searchDepth = parser.getDepth() + 1;
   1735 
   1736         final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
   1737         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
   1738                 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
   1739             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   1740                 continue;
   1741             }
   1742 
   1743             if (parser.getDepth() != searchDepth) {
   1744                 continue;
   1745             }
   1746 
   1747             if (TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
   1748                 final VerifierInfo verifier = parseVerifier(attrs);
   1749                 if (verifier != null) {
   1750                     verifiers.add(verifier);
   1751                 }
   1752             } else if (TAG_APPLICATION.equals(parser.getName())) {
   1753                 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
   1754                     final String attr = attrs.getAttributeName(i);
   1755                     if ("debuggable".equals(attr)) {
   1756                         debuggable = attrs.getAttributeBooleanValue(i, false);
   1757                     }
   1758                     if ("multiArch".equals(attr)) {
   1759                         multiArch = attrs.getAttributeBooleanValue(i, false);
   1760                     }
   1761                     if ("use32bitAbi".equals(attr)) {
   1762                         use32bitAbi = attrs.getAttributeBooleanValue(i, false);
   1763                     }
   1764                     if ("extractNativeLibs".equals(attr)) {
   1765                         extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
   1766                     }
   1767                 }
   1768             } else if (TAG_USES_SPLIT.equals(parser.getName())) {
   1769                 if (usesSplitName != null) {
   1770                     Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
   1771                     continue;
   1772                 }
   1773 
   1774                 usesSplitName = attrs.getAttributeValue(ANDROID_RESOURCES, "name");
   1775                 if (usesSplitName == null) {
   1776                     throw new PackageParserException(
   1777                             PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
   1778                             "<uses-split> tag requires 'android:name' attribute");
   1779                 }
   1780             }
   1781         }
   1782 
   1783         return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
   1784                 configForSplit, usesSplitName, versionCode, versionCodeMajor, revisionCode,
   1785                 installLocation, verifiers, signingDetails, coreApp, debuggable,
   1786                 multiArch, use32bitAbi, extractNativeLibs, isolatedSplits);
   1787     }
   1788 
   1789     /**
   1790      * Parses a child package and adds it to the parent if successful. If you add
   1791      * new tags that need to be supported by child packages make sure to add them
   1792      * to {@link #CHILD_PACKAGE_TAGS}.
   1793      *
   1794      * @param parentPkg The parent that contains the child
   1795      * @param res Resources against which to resolve values
   1796      * @param parser Parser of the manifest
   1797      * @param flags Flags about how to parse
   1798      * @param outError Human readable error if parsing fails
   1799      * @return True of parsing succeeded.
   1800      *
   1801      * @throws XmlPullParserException
   1802      * @throws IOException
   1803      */
   1804     private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser,
   1805             int flags, String[] outError) throws XmlPullParserException, IOException {
   1806         // Make sure we have a valid child package name
   1807         String childPackageName = parser.getAttributeValue(null, "package");
   1808         if (validateName(childPackageName, true, false) != null) {
   1809             mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
   1810             return false;
   1811         }
   1812 
   1813         // Child packages must be unique
   1814         if (childPackageName.equals(parentPkg.packageName)) {
   1815             String message = "Child package name cannot be equal to parent package name: "
   1816                     + parentPkg.packageName;
   1817             Slog.w(TAG, message);
   1818             outError[0] = message;
   1819             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   1820             return false;
   1821         }
   1822 
   1823         // Child packages must be unique
   1824         if (parentPkg.hasChildPackage(childPackageName)) {
   1825             String message = "Duplicate child package:" + childPackageName;
   1826             Slog.w(TAG, message);
   1827             outError[0] = message;
   1828             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   1829             return false;
   1830         }
   1831 
   1832         // Go ahead and parse the child
   1833         Package childPkg = new Package(childPackageName);
   1834 
   1835         // Child package inherits parent version code/name/target SDK
   1836         childPkg.mVersionCode = parentPkg.mVersionCode;
   1837         childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
   1838         childPkg.mVersionName = parentPkg.mVersionName;
   1839         childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
   1840         childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
   1841 
   1842         childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
   1843         if (childPkg == null) {
   1844             // If we got null then error was set during child parsing
   1845             return false;
   1846         }
   1847 
   1848         // Set the parent-child relation
   1849         if (parentPkg.childPackages == null) {
   1850             parentPkg.childPackages = new ArrayList<>();
   1851         }
   1852         parentPkg.childPackages.add(childPkg);
   1853         childPkg.parentPackage = parentPkg;
   1854 
   1855         return true;
   1856     }
   1857 
   1858     /**
   1859      * Parse the manifest of a <em>base APK</em>. When adding new features you
   1860      * need to consider whether they should be supported by split APKs and child
   1861      * packages.
   1862      *
   1863      * @param apkPath The package apk file path
   1864      * @param res The resources from which to resolve values
   1865      * @param parser The manifest parser
   1866      * @param flags Flags how to parse
   1867      * @param outError Human readable error message
   1868      * @return Parsed package or null on error.
   1869      *
   1870      * @throws XmlPullParserException
   1871      * @throws IOException
   1872      */
   1873     private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
   1874             String[] outError) throws XmlPullParserException, IOException {
   1875         final String splitName;
   1876         final String pkgName;
   1877 
   1878         try {
   1879             Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
   1880             pkgName = packageSplit.first;
   1881             splitName = packageSplit.second;
   1882 
   1883             if (!TextUtils.isEmpty(splitName)) {
   1884                 outError[0] = "Expected base APK, but found split " + splitName;
   1885                 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
   1886                 return null;
   1887             }
   1888         } catch (PackageParserException e) {
   1889             mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
   1890             return null;
   1891         }
   1892 
   1893         if (mCallback != null) {
   1894             String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath);
   1895             if (overlayPaths != null && overlayPaths.length > 0) {
   1896                 for (String overlayPath : overlayPaths) {
   1897                     res.getAssets().addOverlayPath(overlayPath);
   1898                 }
   1899             }
   1900         }
   1901 
   1902         final Package pkg = new Package(pkgName);
   1903 
   1904         TypedArray sa = res.obtainAttributes(parser,
   1905                 com.android.internal.R.styleable.AndroidManifest);
   1906 
   1907         pkg.mVersionCode = sa.getInteger(
   1908                 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
   1909         pkg.mVersionCodeMajor = sa.getInteger(
   1910                 com.android.internal.R.styleable.AndroidManifest_versionCodeMajor, 0);
   1911         pkg.applicationInfo.setVersionCode(pkg.getLongVersionCode());
   1912         pkg.baseRevisionCode = sa.getInteger(
   1913                 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
   1914         pkg.mVersionName = sa.getNonConfigurationString(
   1915                 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
   1916         if (pkg.mVersionName != null) {
   1917             pkg.mVersionName = pkg.mVersionName.intern();
   1918         }
   1919 
   1920         pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
   1921 
   1922         pkg.mCompileSdkVersion = sa.getInteger(
   1923                 com.android.internal.R.styleable.AndroidManifest_compileSdkVersion, 0);
   1924         pkg.applicationInfo.compileSdkVersion = pkg.mCompileSdkVersion;
   1925         pkg.mCompileSdkVersionCodename = sa.getNonConfigurationString(
   1926                 com.android.internal.R.styleable.AndroidManifest_compileSdkVersionCodename, 0);
   1927         if (pkg.mCompileSdkVersionCodename != null) {
   1928             pkg.mCompileSdkVersionCodename = pkg.mCompileSdkVersionCodename.intern();
   1929         }
   1930         pkg.applicationInfo.compileSdkVersionCodename = pkg.mCompileSdkVersionCodename;
   1931 
   1932         sa.recycle();
   1933 
   1934         return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
   1935     }
   1936 
   1937     /**
   1938      * This is the common parsing routing for handling parent and child
   1939      * packages in a base APK. The difference between parent and child
   1940      * parsing is that some tags are not supported by child packages as
   1941      * well as some manifest attributes are ignored. The implementation
   1942      * assumes the calling code has already handled the manifest tag if needed
   1943      * (this applies to the parent only).
   1944      *
   1945      * @param pkg The package which to populate
   1946      * @param acceptedTags Which tags to handle, null to handle all
   1947      * @param res Resources against which to resolve values
   1948      * @param parser Parser of the manifest
   1949      * @param flags Flags about how to parse
   1950      * @param outError Human readable error if parsing fails
   1951      * @return The package if parsing succeeded or null.
   1952      *
   1953      * @throws XmlPullParserException
   1954      * @throws IOException
   1955      */
   1956     private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
   1957             XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
   1958             IOException {
   1959         mParseInstrumentationArgs = null;
   1960 
   1961         int type;
   1962         boolean foundApp = false;
   1963 
   1964         TypedArray sa = res.obtainAttributes(parser,
   1965                 com.android.internal.R.styleable.AndroidManifest);
   1966 
   1967         String str = sa.getNonConfigurationString(
   1968                 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
   1969         if (str != null && str.length() > 0) {
   1970             String nameError = validateName(str, true, false);
   1971             if (nameError != null && !"android".equals(pkg.packageName)) {
   1972                 outError[0] = "<manifest> specifies bad sharedUserId name \""
   1973                     + str + "\": " + nameError;
   1974                 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
   1975                 return null;
   1976             }
   1977             pkg.mSharedUserId = str.intern();
   1978             pkg.mSharedUserLabel = sa.getResourceId(
   1979                     com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
   1980         }
   1981 
   1982         pkg.installLocation = sa.getInteger(
   1983                 com.android.internal.R.styleable.AndroidManifest_installLocation,
   1984                 PARSE_DEFAULT_INSTALL_LOCATION);
   1985         pkg.applicationInfo.installLocation = pkg.installLocation;
   1986 
   1987         final int targetSandboxVersion = sa.getInteger(
   1988                 com.android.internal.R.styleable.AndroidManifest_targetSandboxVersion,
   1989                 PARSE_DEFAULT_TARGET_SANDBOX);
   1990         pkg.applicationInfo.targetSandboxVersion = targetSandboxVersion;
   1991 
   1992         /* Set the global "forward lock" flag */
   1993         if ((flags & PARSE_FORWARD_LOCK) != 0) {
   1994             pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
   1995         }
   1996 
   1997         /* Set the global "on SD card" flag */
   1998         if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
   1999             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
   2000         }
   2001 
   2002         if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) {
   2003             pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
   2004         }
   2005 
   2006         // Resource boolean are -1, so 1 means we don't know the value.
   2007         int supportsSmallScreens = 1;
   2008         int supportsNormalScreens = 1;
   2009         int supportsLargeScreens = 1;
   2010         int supportsXLargeScreens = 1;
   2011         int resizeable = 1;
   2012         int anyDensity = 1;
   2013 
   2014         int outerDepth = parser.getDepth();
   2015         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
   2016                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
   2017             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   2018                 continue;
   2019             }
   2020 
   2021             String tagName = parser.getName();
   2022 
   2023             if (acceptedTags != null && !acceptedTags.contains(tagName)) {
   2024                 Slog.w(TAG, "Skipping unsupported element under <manifest>: "
   2025                         + tagName + " at " + mArchiveSourcePath + " "
   2026                         + parser.getPositionDescription());
   2027                 XmlUtils.skipCurrentTag(parser);
   2028                 continue;
   2029             }
   2030 
   2031             if (tagName.equals(TAG_APPLICATION)) {
   2032                 if (foundApp) {
   2033                     if (RIGID_PARSER) {
   2034                         outError[0] = "<manifest> has more than one <application>";
   2035                         mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   2036                         return null;
   2037                     } else {
   2038                         Slog.w(TAG, "<manifest> has more than one <application>");
   2039                         XmlUtils.skipCurrentTag(parser);
   2040                         continue;
   2041                     }
   2042                 }
   2043 
   2044                 foundApp = true;
   2045                 if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
   2046                     return null;
   2047                 }
   2048             } else if (tagName.equals(TAG_OVERLAY)) {
   2049                 sa = res.obtainAttributes(parser,
   2050                         com.android.internal.R.styleable.AndroidManifestResourceOverlay);
   2051                 pkg.mOverlayTarget = sa.getString(
   2052                         com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
   2053                 pkg.mOverlayCategory = sa.getString(
   2054                         com.android.internal.R.styleable.AndroidManifestResourceOverlay_category);
   2055                 pkg.mOverlayPriority = sa.getInt(
   2056                         com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
   2057                         0);
   2058                 pkg.mOverlayIsStatic = sa.getBoolean(
   2059                         com.android.internal.R.styleable.AndroidManifestResourceOverlay_isStatic,
   2060                         false);
   2061                 final String propName = sa.getString(
   2062                         com.android.internal.R.styleable
   2063                         .AndroidManifestResourceOverlay_requiredSystemPropertyName);
   2064                 final String propValue = sa.getString(
   2065                         com.android.internal.R.styleable
   2066                         .AndroidManifestResourceOverlay_requiredSystemPropertyValue);
   2067                 sa.recycle();
   2068 
   2069                 if (pkg.mOverlayTarget == null) {
   2070                     outError[0] = "<overlay> does not specify a target package";
   2071                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   2072                     return null;
   2073                 }
   2074 
   2075                 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
   2076                     outError[0] = "<overlay> priority must be between 0 and 9999";
   2077                     mParseError =
   2078                         PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   2079                     return null;
   2080                 }
   2081 
   2082                 // check to see if overlay should be excluded based on system property condition
   2083                 if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
   2084                     Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and "
   2085                         + pkg.baseCodePath+ ": overlay ignored due to required system property: "
   2086                         + propName + " with value: " + propValue);
   2087                     return null;
   2088                 }
   2089 
   2090                 XmlUtils.skipCurrentTag(parser);
   2091 
   2092             } else if (tagName.equals(TAG_KEY_SETS)) {
   2093                 if (!parseKeySets(pkg, res, parser, outError)) {
   2094                     return null;
   2095                 }
   2096             } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
   2097                 if (!parsePermissionGroup(pkg, flags, res, parser, outError)) {
   2098                     return null;
   2099                 }
   2100             } else if (tagName.equals(TAG_PERMISSION)) {
   2101                 if (!parsePermission(pkg, res, parser, outError)) {
   2102                     return null;
   2103                 }
   2104             } else if (tagName.equals(TAG_PERMISSION_TREE)) {
   2105                 if (!parsePermissionTree(pkg, res, parser, outError)) {
   2106                     return null;
   2107                 }
   2108             } else if (tagName.equals(TAG_USES_PERMISSION)) {
   2109                 if (!parseUsesPermission(pkg, res, parser)) {
   2110                     return null;
   2111                 }
   2112             } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
   2113                     || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
   2114                 if (!parseUsesPermission(pkg, res, parser)) {
   2115                     return null;
   2116                 }
   2117             } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
   2118                 ConfigurationInfo cPref = new ConfigurationInfo();
   2119                 sa = res.obtainAttributes(parser,
   2120                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
   2121                 cPref.reqTouchScreen = sa.getInt(
   2122                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
   2123                         Configuration.TOUCHSCREEN_UNDEFINED);
   2124                 cPref.reqKeyboardType = sa.getInt(
   2125                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
   2126                         Configuration.KEYBOARD_UNDEFINED);
   2127                 if (sa.getBoolean(
   2128                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
   2129                         false)) {
   2130                     cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
   2131                 }
   2132                 cPref.reqNavigation = sa.getInt(
   2133                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
   2134                         Configuration.NAVIGATION_UNDEFINED);
   2135                 if (sa.getBoolean(
   2136                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
   2137                         false)) {
   2138                     cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
   2139                 }
   2140                 sa.recycle();
   2141                 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
   2142 
   2143                 XmlUtils.skipCurrentTag(parser);
   2144 
   2145             } else if (tagName.equals(TAG_USES_FEATURE)) {
   2146                 FeatureInfo fi = parseUsesFeature(res, parser);
   2147                 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
   2148 
   2149                 if (fi.name == null) {
   2150                     ConfigurationInfo cPref = new ConfigurationInfo();
   2151                     cPref.reqGlEsVersion = fi.reqGlEsVersion;
   2152                     pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
   2153                 }
   2154 
   2155                 XmlUtils.skipCurrentTag(parser);
   2156 
   2157             } else if (tagName.equals(TAG_FEATURE_GROUP)) {
   2158                 FeatureGroupInfo group = new FeatureGroupInfo();
   2159                 ArrayList<FeatureInfo> features = null;
   2160                 final int innerDepth = parser.getDepth();
   2161                 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
   2162                         && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
   2163                     if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   2164                         continue;
   2165                     }
   2166 
   2167                     final String innerTagName = parser.getName();
   2168                     if (innerTagName.equals("uses-feature")) {
   2169                         FeatureInfo featureInfo = parseUsesFeature(res, parser);
   2170                         // FeatureGroups are stricter and mandate that
   2171                         // any <uses-feature> declared are mandatory.
   2172                         featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
   2173                         features = ArrayUtils.add(features, featureInfo);
   2174                     } else {
   2175                         Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
   2176                                 " at " + mArchiveSourcePath + " " +
   2177                                 parser.getPositionDescription());
   2178                     }
   2179                     XmlUtils.skipCurrentTag(parser);
   2180                 }
   2181 
   2182                 if (features != null) {
   2183                     group.features = new FeatureInfo[features.size()];
   2184                     group.features = features.toArray(group.features);
   2185                 }
   2186                 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
   2187 
   2188             } else if (tagName.equals(TAG_USES_SDK)) {
   2189                 if (SDK_VERSION > 0) {
   2190                     sa = res.obtainAttributes(parser,
   2191                             com.android.internal.R.styleable.AndroidManifestUsesSdk);
   2192 
   2193                     int minVers = 1;
   2194                     String minCode = null;
   2195                     int targetVers = 0;
   2196                     String targetCode = null;
   2197 
   2198                     TypedValue val = sa.peekValue(
   2199                             com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
   2200                     if (val != null) {
   2201                         if (val.type == TypedValue.TYPE_STRING && val.string != null) {
   2202                             targetCode = minCode = val.string.toString();
   2203                         } else {
   2204                             // If it's not a string, it's an integer.
   2205                             targetVers = minVers = val.data;
   2206                         }
   2207                     }
   2208 
   2209                     val = sa.peekValue(
   2210                             com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
   2211                     if (val != null) {
   2212                         if (val.type == TypedValue.TYPE_STRING && val.string != null) {
   2213                             targetCode = val.string.toString();
   2214                             if (minCode == null) {
   2215                                 minCode = targetCode;
   2216                             }
   2217                         } else {
   2218                             // If it's not a string, it's an integer.
   2219                             targetVers = val.data;
   2220                         }
   2221                     }
   2222 
   2223                     sa.recycle();
   2224 
   2225                     final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers, minCode,
   2226                             SDK_VERSION, SDK_CODENAMES, outError);
   2227                     if (minSdkVersion < 0) {
   2228                         mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
   2229                         return null;
   2230                     }
   2231 
   2232                     boolean defaultToCurrentDevBranch = (flags & PARSE_FORCE_SDK) != 0;
   2233                     final int targetSdkVersion = PackageParser.computeTargetSdkVersion(targetVers,
   2234                             targetCode, SDK_CODENAMES, outError, defaultToCurrentDevBranch);
   2235                     if (targetSdkVersion < 0) {
   2236                         mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
   2237                         return null;
   2238                     }
   2239 
   2240                     pkg.applicationInfo.minSdkVersion = minSdkVersion;
   2241                     pkg.applicationInfo.targetSdkVersion = targetSdkVersion;
   2242                 }
   2243 
   2244                 XmlUtils.skipCurrentTag(parser);
   2245 
   2246             } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
   2247                 sa = res.obtainAttributes(parser,
   2248                         com.android.internal.R.styleable.AndroidManifestSupportsScreens);
   2249 
   2250                 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
   2251                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
   2252                         0);
   2253                 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
   2254                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
   2255                         0);
   2256                 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
   2257                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
   2258                         0);
   2259 
   2260                 // This is a trick to get a boolean and still able to detect
   2261                 // if a value was actually set.
   2262                 supportsSmallScreens = sa.getInteger(
   2263                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
   2264                         supportsSmallScreens);
   2265                 supportsNormalScreens = sa.getInteger(
   2266                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
   2267                         supportsNormalScreens);
   2268                 supportsLargeScreens = sa.getInteger(
   2269                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
   2270                         supportsLargeScreens);
   2271                 supportsXLargeScreens = sa.getInteger(
   2272                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
   2273                         supportsXLargeScreens);
   2274                 resizeable = sa.getInteger(
   2275                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
   2276                         resizeable);
   2277                 anyDensity = sa.getInteger(
   2278                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
   2279                         anyDensity);
   2280 
   2281                 sa.recycle();
   2282 
   2283                 XmlUtils.skipCurrentTag(parser);
   2284 
   2285             } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
   2286                 sa = res.obtainAttributes(parser,
   2287                         com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
   2288 
   2289                 // Note: don't allow this value to be a reference to a resource
   2290                 // that may change.
   2291                 String name = sa.getNonResourceString(
   2292                         com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
   2293 
   2294                 sa.recycle();
   2295 
   2296                 if (name != null) {
   2297                     if (pkg.protectedBroadcasts == null) {
   2298                         pkg.protectedBroadcasts = new ArrayList<String>();
   2299                     }
   2300                     if (!pkg.protectedBroadcasts.contains(name)) {
   2301                         pkg.protectedBroadcasts.add(name.intern());
   2302                     }
   2303                 }
   2304 
   2305                 XmlUtils.skipCurrentTag(parser);
   2306 
   2307             } else if (tagName.equals(TAG_INSTRUMENTATION)) {
   2308                 if (parseInstrumentation(pkg, res, parser, outError) == null) {
   2309                     return null;
   2310                 }
   2311             } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
   2312                 sa = res.obtainAttributes(parser,
   2313                         com.android.internal.R.styleable.AndroidManifestOriginalPackage);
   2314 
   2315                 String orig =sa.getNonConfigurationString(
   2316                         com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
   2317                 if (!pkg.packageName.equals(orig)) {
   2318                     if (pkg.mOriginalPackages == null) {
   2319                         pkg.mOriginalPackages = new ArrayList<String>();
   2320                         pkg.mRealPackage = pkg.packageName;
   2321                     }
   2322                     pkg.mOriginalPackages.add(orig);
   2323                 }
   2324 
   2325                 sa.recycle();
   2326 
   2327                 XmlUtils.skipCurrentTag(parser);
   2328 
   2329             } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
   2330                 sa = res.obtainAttributes(parser,
   2331                         com.android.internal.R.styleable.AndroidManifestOriginalPackage);
   2332 
   2333                 String name = sa.getNonConfigurationString(
   2334                         com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
   2335 
   2336                 sa.recycle();
   2337 
   2338                 if (name != null) {
   2339                     if (pkg.mAdoptPermissions == null) {
   2340                         pkg.mAdoptPermissions = new ArrayList<String>();
   2341                     }
   2342                     pkg.mAdoptPermissions.add(name);
   2343                 }
   2344 
   2345                 XmlUtils.skipCurrentTag(parser);
   2346 
   2347             } else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
   2348                 // Just skip this tag
   2349                 XmlUtils.skipCurrentTag(parser);
   2350                 continue;
   2351 
   2352             } else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) {
   2353                 // Just skip this tag
   2354                 XmlUtils.skipCurrentTag(parser);
   2355                 continue;
   2356             } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
   2357                 XmlUtils.skipCurrentTag(parser);
   2358                 continue;
   2359 
   2360             } else if (tagName.equals(TAG_EAT_COMMENT)) {
   2361                 // Just skip this tag
   2362                 XmlUtils.skipCurrentTag(parser);
   2363                 continue;
   2364 
   2365             } else if (tagName.equals(TAG_PACKAGE)) {
   2366                 if (!MULTI_PACKAGE_APK_ENABLED) {
   2367                     XmlUtils.skipCurrentTag(parser);
   2368                     continue;
   2369                 }
   2370                 if (!parseBaseApkChild(pkg, res, parser, flags, outError)) {
   2371                     // If parsing a child failed the error is already set
   2372                     return null;
   2373                 }
   2374 
   2375             } else if (tagName.equals(TAG_RESTRICT_UPDATE)) {
   2376                 if ((flags & PARSE_IS_SYSTEM_DIR) != 0) {
   2377                     sa = res.obtainAttributes(parser,
   2378                             com.android.internal.R.styleable.AndroidManifestRestrictUpdate);
   2379                     final String hash = sa.getNonConfigurationString(
   2380                             com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0);
   2381                     sa.recycle();
   2382 
   2383                     pkg.restrictUpdateHash = null;
   2384                     if (hash != null) {
   2385                         final int hashLength = hash.length();
   2386                         final byte[] hashBytes = new byte[hashLength / 2];
   2387                         for (int i = 0; i < hashLength; i += 2){
   2388                             hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4)
   2389                                     + Character.digit(hash.charAt(i + 1), 16));
   2390                         }
   2391                         pkg.restrictUpdateHash = hashBytes;
   2392                     }
   2393                 }
   2394 
   2395                 XmlUtils.skipCurrentTag(parser);
   2396 
   2397             } else if (RIGID_PARSER) {
   2398                 outError[0] = "Bad element under <manifest>: "
   2399                     + parser.getName();
   2400                 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   2401                 return null;
   2402 
   2403             } else {
   2404                 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
   2405                         + " at " + mArchiveSourcePath + " "
   2406                         + parser.getPositionDescription());
   2407                 XmlUtils.skipCurrentTag(parser);
   2408                 continue;
   2409             }
   2410         }
   2411 
   2412         if (!foundApp && pkg.instrumentation.size() == 0) {
   2413             outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
   2414             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
   2415         }
   2416 
   2417         final int NP = PackageParser.NEW_PERMISSIONS.length;
   2418         StringBuilder implicitPerms = null;
   2419         for (int ip=0; ip<NP; ip++) {
   2420             final PackageParser.NewPermissionInfo npi
   2421                     = PackageParser.NEW_PERMISSIONS[ip];
   2422             if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
   2423                 break;
   2424             }
   2425             if (!pkg.requestedPermissions.contains(npi.name)) {
   2426                 if (implicitPerms == null) {
   2427                     implicitPerms = new StringBuilder(128);
   2428                     implicitPerms.append(pkg.packageName);
   2429                     implicitPerms.append(": compat added ");
   2430                 } else {
   2431                     implicitPerms.append(' ');
   2432                 }
   2433                 implicitPerms.append(npi.name);
   2434                 pkg.requestedPermissions.add(npi.name);
   2435             }
   2436         }
   2437         if (implicitPerms != null) {
   2438             Slog.i(TAG, implicitPerms.toString());
   2439         }
   2440 
   2441         final int NS = PackageParser.SPLIT_PERMISSIONS.length;
   2442         for (int is=0; is<NS; is++) {
   2443             final PackageParser.SplitPermissionInfo spi
   2444                     = PackageParser.SPLIT_PERMISSIONS[is];
   2445             if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
   2446                     || !pkg.requestedPermissions.contains(spi.rootPerm)) {
   2447                 continue;
   2448             }
   2449             for (int in=0; in<spi.newPerms.length; in++) {
   2450                 final String perm = spi.newPerms[in];
   2451                 if (!pkg.requestedPermissions.contains(perm)) {
   2452                     pkg.requestedPermissions.add(perm);
   2453                 }
   2454             }
   2455         }
   2456 
   2457         if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
   2458                 && pkg.applicationInfo.targetSdkVersion
   2459                         >= android.os.Build.VERSION_CODES.DONUT)) {
   2460             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
   2461         }
   2462         if (supportsNormalScreens != 0) {
   2463             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
   2464         }
   2465         if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
   2466                 && pkg.applicationInfo.targetSdkVersion
   2467                         >= android.os.Build.VERSION_CODES.DONUT)) {
   2468             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
   2469         }
   2470         if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
   2471                 && pkg.applicationInfo.targetSdkVersion
   2472                         >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
   2473             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
   2474         }
   2475         if (resizeable < 0 || (resizeable > 0
   2476                 && pkg.applicationInfo.targetSdkVersion
   2477                         >= android.os.Build.VERSION_CODES.DONUT)) {
   2478             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
   2479         }
   2480         if (anyDensity < 0 || (anyDensity > 0
   2481                 && pkg.applicationInfo.targetSdkVersion
   2482                         >= android.os.Build.VERSION_CODES.DONUT)) {
   2483             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
   2484         }
   2485 
   2486         // At this point we can check if an application is not supporting densities and hence
   2487         // cannot be windowed / resized. Note that an SDK version of 0 is common for
   2488         // pre-Doughnut applications.
   2489         if (pkg.applicationInfo.usesCompatibilityMode()) {
   2490             adjustPackageToBeUnresizeableAndUnpipable(pkg);
   2491         }
   2492         return pkg;
   2493     }
   2494 
   2495     private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
   2496 
   2497         if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
   2498             if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
   2499                 // malformed condition - incomplete
   2500                 Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName
   2501                     + "=" + propValue + "' - require both requiredSystemPropertyName"
   2502                     + " AND requiredSystemPropertyValue to be specified.");
   2503                 return false;
   2504             }
   2505             // no valid condition set - so no exclusion criteria, overlay will be included.
   2506             return true;
   2507         }
   2508 
   2509         // check property value - make sure it is both set and equal to expected value
   2510         final String currValue = SystemProperties.get(propName);
   2511         return (currValue != null && currValue.equals(propValue));
   2512     }
   2513 
   2514     /**
   2515      * This is a pre-density application which will get scaled - instead of being pixel perfect.
   2516      * This type of application is not resizable.
   2517      *
   2518      * @param pkg The package which needs to be marked as unresizable.
   2519      */
   2520     private void adjustPackageToBeUnresizeableAndUnpipable(Package pkg) {
   2521         for (Activity a : pkg.activities) {
   2522             a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
   2523             a.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE;
   2524         }
   2525     }
   2526 
   2527     /**
   2528      * Computes the targetSdkVersion to use at runtime. If the package is not
   2529      * compatible with this platform, populates {@code outError[0]} with an
   2530      * error message.
   2531      * <p>
   2532      * If {@code targetCode} is not specified, e.g. the value is {@code null},
   2533      * then the {@code targetVers} will be returned unmodified.
   2534      * <p>
   2535      * Otherwise, the behavior varies based on whether the current platform
   2536      * is a pre-release version, e.g. the {@code platformSdkCodenames} array
   2537      * has length > 0:
   2538      * <ul>
   2539      * <li>If this is a pre-release platform and the value specified by
   2540      * {@code targetCode} is contained within the array of allowed pre-release
   2541      * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
   2542      * <li>If this is a released platform, this method will return -1 to
   2543      * indicate that the package is not compatible with this platform.
   2544      * </ul>
   2545      *
   2546      * @param targetVers targetSdkVersion number, if specified in the
   2547      *                   application manifest, or 0 otherwise
   2548      * @param targetCode targetSdkVersion code, if specified in the application
   2549      *                   manifest, or {@code null} otherwise
   2550      * @param platformSdkCodenames array of allowed pre-release SDK codenames
   2551      *                             for this platform
   2552      * @param outError output array to populate with error, if applicable
   2553      * @param forceCurrentDev if development target code is not available, use the current
   2554      *                        development version by default.
   2555      * @return the targetSdkVersion to use at runtime, or -1 if the package is
   2556      *         not compatible with this platform
   2557      * @hide Exposed for unit testing only.
   2558      */
   2559     @TestApi
   2560     public static int computeTargetSdkVersion(@IntRange(from = 0) int targetVers,
   2561             @Nullable String targetCode, @NonNull String[] platformSdkCodenames,
   2562             @NonNull String[] outError, boolean forceCurrentDev) {
   2563         // If it's a release SDK, return the version number unmodified.
   2564         if (targetCode == null) {
   2565             return targetVers;
   2566         }
   2567 
   2568         // If it's a pre-release SDK and the codename matches this platform, it
   2569         // definitely targets this SDK.
   2570         if (ArrayUtils.contains(platformSdkCodenames, targetCode) || forceCurrentDev) {
   2571             return Build.VERSION_CODES.CUR_DEVELOPMENT;
   2572         }
   2573 
   2574         // Otherwise, we're looking at an incompatible pre-release SDK.
   2575         if (platformSdkCodenames.length > 0) {
   2576             outError[0] = "Requires development platform " + targetCode
   2577                     + " (current platform is any of "
   2578                     + Arrays.toString(platformSdkCodenames) + ")";
   2579         } else {
   2580             outError[0] = "Requires development platform " + targetCode
   2581                     + " but this is a release platform.";
   2582         }
   2583         return -1;
   2584     }
   2585 
   2586     /**
   2587      * Computes the minSdkVersion to use at runtime. If the package is not
   2588      * compatible with this platform, populates {@code outError[0]} with an
   2589      * error message.
   2590      * <p>
   2591      * If {@code minCode} is not specified, e.g. the value is {@code null},
   2592      * then behavior varies based on the {@code platformSdkVersion}:
   2593      * <ul>
   2594      * <li>If the platform SDK version is greater than or equal to the
   2595      * {@code minVers}, returns the {@code mniVers} unmodified.
   2596      * <li>Otherwise, returns -1 to indicate that the package is not
   2597      * compatible with this platform.
   2598      * </ul>
   2599      * <p>
   2600      * Otherwise, the behavior varies based on whether the current platform
   2601      * is a pre-release version, e.g. the {@code platformSdkCodenames} array
   2602      * has length > 0:
   2603      * <ul>
   2604      * <li>If this is a pre-release platform and the value specified by
   2605      * {@code targetCode} is contained within the array of allowed pre-release
   2606      * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
   2607      * <li>If this is a released platform, this method will return -1 to
   2608      * indicate that the package is not compatible with this platform.
   2609      * </ul>
   2610      *
   2611      * @param minVers minSdkVersion number, if specified in the application
   2612      *                manifest, or 1 otherwise
   2613      * @param minCode minSdkVersion code, if specified in the application
   2614      *                manifest, or {@code null} otherwise
   2615      * @param platformSdkVersion platform SDK version number, typically
   2616      *                           Build.VERSION.SDK_INT
   2617      * @param platformSdkCodenames array of allowed prerelease SDK codenames
   2618      *                             for this platform
   2619      * @param outError output array to populate with error, if applicable
   2620      * @return the minSdkVersion to use at runtime, or -1 if the package is not
   2621      *         compatible with this platform
   2622      * @hide Exposed for unit testing only.
   2623      */
   2624     @TestApi
   2625     public static int computeMinSdkVersion(@IntRange(from = 1) int minVers,
   2626             @Nullable String minCode, @IntRange(from = 1) int platformSdkVersion,
   2627             @NonNull String[] platformSdkCodenames, @NonNull String[] outError) {
   2628         // If it's a release SDK, make sure we meet the minimum SDK requirement.
   2629         if (minCode == null) {
   2630             if (minVers <= platformSdkVersion) {
   2631                 return minVers;
   2632             }
   2633 
   2634             // We don't meet the minimum SDK requirement.
   2635             outError[0] = "Requires newer sdk version #" + minVers
   2636                     + " (current version is #" + platformSdkVersion + ")";
   2637             return -1;
   2638         }
   2639 
   2640         // If it's a pre-release SDK and the codename matches this platform, we
   2641         // definitely meet the minimum SDK requirement.
   2642         if (ArrayUtils.contains(platformSdkCodenames, minCode)) {
   2643             return Build.VERSION_CODES.CUR_DEVELOPMENT;
   2644         }
   2645 
   2646         // Otherwise, we're looking at an incompatible pre-release SDK.
   2647         if (platformSdkCodenames.length > 0) {
   2648             outError[0] = "Requires development platform " + minCode
   2649                     + " (current platform is any of "
   2650                     + Arrays.toString(platformSdkCodenames) + ")";
   2651         } else {
   2652             outError[0] = "Requires development platform " + minCode
   2653                     + " but this is a release platform.";
   2654         }
   2655         return -1;
   2656     }
   2657 
   2658     private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) {
   2659         FeatureInfo fi = new FeatureInfo();
   2660         TypedArray sa = res.obtainAttributes(attrs,
   2661                 com.android.internal.R.styleable.AndroidManifestUsesFeature);
   2662         // Note: don't allow this value to be a reference to a resource
   2663         // that may change.
   2664         fi.name = sa.getNonResourceString(
   2665                 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
   2666         fi.version = sa.getInt(
   2667                 com.android.internal.R.styleable.AndroidManifestUsesFeature_version, 0);
   2668         if (fi.name == null) {
   2669             fi.reqGlEsVersion = sa.getInt(
   2670                         com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
   2671                         FeatureInfo.GL_ES_VERSION_UNDEFINED);
   2672         }
   2673         if (sa.getBoolean(
   2674                 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) {
   2675             fi.flags |= FeatureInfo.FLAG_REQUIRED;
   2676         }
   2677         sa.recycle();
   2678         return fi;
   2679     }
   2680 
   2681     private boolean parseUsesStaticLibrary(Package pkg, Resources res, XmlResourceParser parser,
   2682             String[] outError) throws XmlPullParserException, IOException {
   2683         TypedArray sa = res.obtainAttributes(parser,
   2684                 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary);
   2685 
   2686         // Note: don't allow this value to be a reference to a resource that may change.
   2687         String lname = sa.getNonResourceString(
   2688                 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
   2689         final int version = sa.getInt(
   2690                 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary_version, -1);
   2691         String certSha256Digest = sa.getNonResourceString(com.android.internal.R.styleable
   2692                 .AndroidManifestUsesStaticLibrary_certDigest);
   2693         sa.recycle();
   2694 
   2695         // Since an APK providing a static shared lib can only provide the lib - fail if malformed
   2696         if (lname == null || version < 0 || certSha256Digest == null) {
   2697             outError[0] = "Bad uses-static-library declaration name: " + lname + " version: "
   2698                     + version + " certDigest" + certSha256Digest;
   2699             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   2700             XmlUtils.skipCurrentTag(parser);
   2701             return false;
   2702         }
   2703 
   2704         // Can depend only on one version of the same library
   2705         if (pkg.usesStaticLibraries != null && pkg.usesStaticLibraries.contains(lname)) {
   2706             outError[0] = "Depending on multiple versions of static library " + lname;
   2707             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   2708             XmlUtils.skipCurrentTag(parser);
   2709             return false;
   2710         }
   2711 
   2712         lname = lname.intern();
   2713         // We allow ":" delimiters in the SHA declaration as this is the format
   2714         // emitted by the certtool making it easy for developers to copy/paste.
   2715         certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
   2716 
   2717         // Fot apps targeting O-MR1 we require explicit enumeration of all certs.
   2718         String[] additionalCertSha256Digests = EmptyArray.STRING;
   2719         if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O_MR1) {
   2720             additionalCertSha256Digests = parseAdditionalCertificates(res, parser, outError);
   2721             if (additionalCertSha256Digests == null) {
   2722                 return false;
   2723             }
   2724         } else {
   2725             XmlUtils.skipCurrentTag(parser);
   2726         }
   2727 
   2728         final String[] certSha256Digests = new String[additionalCertSha256Digests.length + 1];
   2729         certSha256Digests[0] = certSha256Digest;
   2730         System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests,
   2731                 1, additionalCertSha256Digests.length);
   2732 
   2733         pkg.usesStaticLibraries = ArrayUtils.add(pkg.usesStaticLibraries, lname);
   2734         pkg.usesStaticLibrariesVersions = ArrayUtils.appendLong(
   2735                 pkg.usesStaticLibrariesVersions, version, true);
   2736         pkg.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String[].class,
   2737                 pkg.usesStaticLibrariesCertDigests, certSha256Digests, true);
   2738 
   2739         return true;
   2740     }
   2741 
   2742     private String[] parseAdditionalCertificates(Resources resources, XmlResourceParser parser,
   2743             String[] outError) throws XmlPullParserException, IOException {
   2744         String[] certSha256Digests = EmptyArray.STRING;
   2745 
   2746         int outerDepth = parser.getDepth();
   2747         int type;
   2748         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
   2749                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
   2750             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   2751                 continue;
   2752             }
   2753 
   2754             final String nodeName = parser.getName();
   2755             if (nodeName.equals("additional-certificate")) {
   2756                 final TypedArray sa = resources.obtainAttributes(parser, com.android.internal.
   2757                         R.styleable.AndroidManifestAdditionalCertificate);
   2758                 String certSha256Digest = sa.getNonResourceString(com.android.internal.
   2759                         R.styleable.AndroidManifestAdditionalCertificate_certDigest);
   2760                 sa.recycle();
   2761 
   2762                 if (TextUtils.isEmpty(certSha256Digest)) {
   2763                     outError[0] = "Bad additional-certificate declaration with empty"
   2764                             + " certDigest:" + certSha256Digest;
   2765                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   2766                     XmlUtils.skipCurrentTag(parser);
   2767                     sa.recycle();
   2768                     return null;
   2769                 }
   2770 
   2771                 // We allow ":" delimiters in the SHA declaration as this is the format
   2772                 // emitted by the certtool making it easy for developers to copy/paste.
   2773                 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
   2774                 certSha256Digests = ArrayUtils.appendElement(String.class,
   2775                         certSha256Digests, certSha256Digest);
   2776             } else {
   2777                 XmlUtils.skipCurrentTag(parser);
   2778             }
   2779         }
   2780 
   2781         return certSha256Digests;
   2782     }
   2783 
   2784     private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
   2785             throws XmlPullParserException, IOException {
   2786         TypedArray sa = res.obtainAttributes(parser,
   2787                 com.android.internal.R.styleable.AndroidManifestUsesPermission);
   2788 
   2789         // Note: don't allow this value to be a reference to a resource
   2790         // that may change.
   2791         String name = sa.getNonResourceString(
   2792                 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
   2793 
   2794         int maxSdkVersion = 0;
   2795         TypedValue val = sa.peekValue(
   2796                 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
   2797         if (val != null) {
   2798             if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
   2799                 maxSdkVersion = val.data;
   2800             }
   2801         }
   2802 
   2803         final String requiredFeature = sa.getNonConfigurationString(
   2804                 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredFeature, 0);
   2805 
   2806         final String requiredNotfeature = sa.getNonConfigurationString(
   2807                 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);
   2808 
   2809         sa.recycle();
   2810 
   2811         XmlUtils.skipCurrentTag(parser);
   2812 
   2813         if (name == null) {
   2814             return true;
   2815         }
   2816 
   2817         if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) {
   2818             return true;
   2819         }
   2820 
   2821         // Only allow requesting this permission if the platform supports the given feature.
   2822         if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(requiredFeature)) {
   2823             return true;
   2824         }
   2825 
   2826         // Only allow requesting this permission if the platform doesn't support the given feature.
   2827         if (requiredNotfeature != null && mCallback != null
   2828                 && mCallback.hasFeature(requiredNotfeature)) {
   2829             return true;
   2830         }
   2831 
   2832         int index = pkg.requestedPermissions.indexOf(name);
   2833         if (index == -1) {
   2834             pkg.requestedPermissions.add(name.intern());
   2835         } else {
   2836             Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
   2837                     + name + " in package: " + pkg.packageName + " at: "
   2838                     + parser.getPositionDescription());
   2839         }
   2840 
   2841         return true;
   2842     }
   2843 
   2844     private static String buildClassName(String pkg, CharSequence clsSeq,
   2845             String[] outError) {
   2846         if (clsSeq == null || clsSeq.length() <= 0) {
   2847             outError[0] = "Empty class name in package " + pkg;
   2848             return null;
   2849         }
   2850         String cls = clsSeq.toString();
   2851         char c = cls.charAt(0);
   2852         if (c == '.') {
   2853             return pkg + cls;
   2854         }
   2855         if (cls.indexOf('.') < 0) {
   2856             StringBuilder b = new StringBuilder(pkg);
   2857             b.append('.');
   2858             b.append(cls);
   2859             return b.toString();
   2860         }
   2861         return cls;
   2862     }
   2863 
   2864     private static String buildCompoundName(String pkg,
   2865             CharSequence procSeq, String type, String[] outError) {
   2866         String proc = procSeq.toString();
   2867         char c = proc.charAt(0);
   2868         if (pkg != null && c == ':') {
   2869             if (proc.length() < 2) {
   2870                 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
   2871                         + ": must be at least two characters";
   2872                 return null;
   2873             }
   2874             String subName = proc.substring(1);
   2875             String nameError = validateName(subName, false, false);
   2876             if (nameError != null) {
   2877                 outError[0] = "Invalid " + type + " name " + proc + " in package "
   2878                         + pkg + ": " + nameError;
   2879                 return null;
   2880             }
   2881             return pkg + proc;
   2882         }
   2883         String nameError = validateName(proc, true, false);
   2884         if (nameError != null && !"system".equals(proc)) {
   2885             outError[0] = "Invalid " + type + " name " + proc + " in package "
   2886                     + pkg + ": " + nameError;
   2887             return null;
   2888         }
   2889         return proc;
   2890     }
   2891 
   2892     private static String buildProcessName(String pkg, String defProc,
   2893             CharSequence procSeq, int flags, String[] separateProcesses,
   2894             String[] outError) {
   2895         if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
   2896             return defProc != null ? defProc : pkg;
   2897         }
   2898         if (separateProcesses != null) {
   2899             for (int i=separateProcesses.length-1; i>=0; i--) {
   2900                 String sp = separateProcesses[i];
   2901                 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
   2902                     return pkg;
   2903                 }
   2904             }
   2905         }
   2906         if (procSeq == null || procSeq.length() <= 0) {
   2907             return defProc;
   2908         }
   2909         return TextUtils.safeIntern(buildCompoundName(pkg, procSeq, "process", outError));
   2910     }
   2911 
   2912     private static String buildTaskAffinityName(String pkg, String defProc,
   2913             CharSequence procSeq, String[] outError) {
   2914         if (procSeq == null) {
   2915             return defProc;
   2916         }
   2917         if (procSeq.length() <= 0) {
   2918             return null;
   2919         }
   2920         return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
   2921     }
   2922 
   2923     private boolean parseKeySets(Package owner, Resources res,
   2924             XmlResourceParser parser, String[] outError)
   2925             throws XmlPullParserException, IOException {
   2926         // we've encountered the 'key-sets' tag
   2927         // all the keys and keysets that we want must be defined here
   2928         // so we're going to iterate over the parser and pull out the things we want
   2929         int outerDepth = parser.getDepth();
   2930         int currentKeySetDepth = -1;
   2931         int type;
   2932         String currentKeySet = null;
   2933         ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
   2934         ArraySet<String> upgradeKeySets = new ArraySet<String>();
   2935         ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
   2936         ArraySet<String> improperKeySets = new ArraySet<String>();
   2937         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
   2938                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
   2939             if (type == XmlPullParser.END_TAG) {
   2940                 if (parser.getDepth() == currentKeySetDepth) {
   2941                     currentKeySet = null;
   2942                     currentKeySetDepth = -1;
   2943                 }
   2944                 continue;
   2945             }
   2946             String tagName = parser.getName();
   2947             if (tagName.equals("key-set")) {
   2948                 if (currentKeySet != null) {
   2949                     outError[0] = "Improperly nested 'key-set' tag at "
   2950                             + parser.getPositionDescription();
   2951                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   2952                     return false;
   2953                 }
   2954                 final TypedArray sa = res.obtainAttributes(parser,
   2955                         com.android.internal.R.styleable.AndroidManifestKeySet);
   2956                 final String keysetName = sa.getNonResourceString(
   2957                     com.android.internal.R.styleable.AndroidManifestKeySet_name);
   2958                 definedKeySets.put(keysetName, new ArraySet<String>());
   2959                 currentKeySet = keysetName;
   2960                 currentKeySetDepth = parser.getDepth();
   2961                 sa.recycle();
   2962             } else if (tagName.equals("public-key")) {
   2963                 if (currentKeySet == null) {
   2964                     outError[0] = "Improperly nested 'key-set' tag at "
   2965                             + parser.getPositionDescription();
   2966                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   2967                     return false;
   2968                 }
   2969                 final TypedArray sa = res.obtainAttributes(parser,
   2970                         com.android.internal.R.styleable.AndroidManifestPublicKey);
   2971                 final String publicKeyName = sa.getNonResourceString(
   2972                         com.android.internal.R.styleable.AndroidManifestPublicKey_name);
   2973                 final String encodedKey = sa.getNonResourceString(
   2974                             com.android.internal.R.styleable.AndroidManifestPublicKey_value);
   2975                 if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
   2976                     outError[0] = "'public-key' " + publicKeyName + " must define a public-key value"
   2977                             + " on first use at " + parser.getPositionDescription();
   2978                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   2979                     sa.recycle();
   2980                     return false;
   2981                 } else if (encodedKey != null) {
   2982                     PublicKey currentKey = parsePublicKey(encodedKey);
   2983                     if (currentKey == null) {
   2984                         Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
   2985                                 + parser.getPositionDescription() + " key-set " + currentKeySet
   2986                                 + " will not be added to the package's defined key-sets.");
   2987                         sa.recycle();
   2988                         improperKeySets.add(currentKeySet);
   2989                         XmlUtils.skipCurrentTag(parser);
   2990                         continue;
   2991                     }
   2992                     if (publicKeys.get(publicKeyName) == null
   2993                             || publicKeys.get(publicKeyName).equals(currentKey)) {
   2994 
   2995                         /* public-key first definition, or matches old definition */
   2996                         publicKeys.put(publicKeyName, currentKey);
   2997                     } else {
   2998                         outError[0] = "Value of 'public-key' " + publicKeyName
   2999                                + " conflicts with previously defined value at "
   3000                                + parser.getPositionDescription();
   3001                         mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3002                         sa.recycle();
   3003                         return false;
   3004                     }
   3005                 }
   3006                 definedKeySets.get(currentKeySet).add(publicKeyName);
   3007                 sa.recycle();
   3008                 XmlUtils.skipCurrentTag(parser);
   3009             } else if (tagName.equals("upgrade-key-set")) {
   3010                 final TypedArray sa = res.obtainAttributes(parser,
   3011                         com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
   3012                 String name = sa.getNonResourceString(
   3013                         com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
   3014                 upgradeKeySets.add(name);
   3015                 sa.recycle();
   3016                 XmlUtils.skipCurrentTag(parser);
   3017             } else if (RIGID_PARSER) {
   3018                 outError[0] = "Bad element under <key-sets>: " + parser.getName()
   3019                         + " at " + mArchiveSourcePath + " "
   3020                         + parser.getPositionDescription();
   3021                 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3022                 return false;
   3023             } else {
   3024                 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
   3025                         + " at " + mArchiveSourcePath + " "
   3026                         + parser.getPositionDescription());
   3027                 XmlUtils.skipCurrentTag(parser);
   3028                 continue;
   3029             }
   3030         }
   3031         Set<String> publicKeyNames = publicKeys.keySet();
   3032         if (publicKeyNames.removeAll(definedKeySets.keySet())) {
   3033             outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
   3034                     + "'key-set' and 'public-key' names must be distinct.";
   3035             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3036             return false;
   3037         }
   3038         owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
   3039         for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) {
   3040             final String keySetName = e.getKey();
   3041             if (e.getValue().size() == 0) {
   3042                 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
   3043                         + "'key-set' " + keySetName + " has no valid associated 'public-key'."
   3044                         + " Not including in package's defined key-sets.");
   3045                 continue;
   3046             } else if (improperKeySets.contains(keySetName)) {
   3047                 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
   3048                         + "'key-set' " + keySetName + " contained improper 'public-key'"
   3049                         + " tags. Not including in package's defined key-sets.");
   3050                 continue;
   3051             }
   3052             owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
   3053             for (String s : e.getValue()) {
   3054                 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
   3055             }
   3056         }
   3057         if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
   3058             owner.mUpgradeKeySets = upgradeKeySets;
   3059         } else {
   3060             outError[0] ="Package" + owner.packageName + " AndroidManifext.xml "
   3061                    + "does not define all 'upgrade-key-set's .";
   3062             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3063             return false;
   3064         }
   3065         return true;
   3066     }
   3067 
   3068     private boolean parsePermissionGroup(Package owner, int flags, Resources res,
   3069             XmlResourceParser parser, String[] outError)
   3070             throws XmlPullParserException, IOException {
   3071         PermissionGroup perm = new PermissionGroup(owner);
   3072 
   3073         TypedArray sa = res.obtainAttributes(parser,
   3074                 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
   3075         if (!parsePackageItemInfo(owner, perm.info, outError,
   3076                 "<permission-group>", sa, true /*nameRequired*/,
   3077                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
   3078                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
   3079                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
   3080                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_roundIcon,
   3081                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
   3082                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
   3083             sa.recycle();
   3084             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3085             return false;
   3086         }
   3087 
   3088         perm.info.descriptionRes = sa.getResourceId(
   3089                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
   3090                 0);
   3091         perm.info.requestRes = sa.getResourceId(
   3092                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_request, 0);
   3093         perm.info.flags = sa.getInt(
   3094                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
   3095         perm.info.priority = sa.getInt(
   3096                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
   3097 
   3098         sa.recycle();
   3099 
   3100         if (!parseAllMetaData(res, parser, "<permission-group>", perm,
   3101                 outError)) {
   3102             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3103             return false;
   3104         }
   3105 
   3106         owner.permissionGroups.add(perm);
   3107 
   3108         return true;
   3109     }
   3110 
   3111     private boolean parsePermission(Package owner, Resources res,
   3112             XmlResourceParser parser, String[] outError)
   3113         throws XmlPullParserException, IOException {
   3114 
   3115         TypedArray sa = res.obtainAttributes(parser,
   3116                 com.android.internal.R.styleable.AndroidManifestPermission);
   3117 
   3118         Permission perm = new Permission(owner);
   3119         if (!parsePackageItemInfo(owner, perm.info, outError,
   3120                 "<permission>", sa, true /*nameRequired*/,
   3121                 com.android.internal.R.styleable.AndroidManifestPermission_name,
   3122                 com.android.internal.R.styleable.AndroidManifestPermission_label,
   3123                 com.android.internal.R.styleable.AndroidManifestPermission_icon,
   3124                 com.android.internal.R.styleable.AndroidManifestPermission_roundIcon,
   3125                 com.android.internal.R.styleable.AndroidManifestPermission_logo,
   3126                 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
   3127             sa.recycle();
   3128             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3129             return false;
   3130         }
   3131 
   3132         // Note: don't allow this value to be a reference to a resource
   3133         // that may change.
   3134         perm.info.group = sa.getNonResourceString(
   3135                 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
   3136         if (perm.info.group != null) {
   3137             perm.info.group = perm.info.group.intern();
   3138         }
   3139 
   3140         perm.info.descriptionRes = sa.getResourceId(
   3141                 com.android.internal.R.styleable.AndroidManifestPermission_description,
   3142                 0);
   3143 
   3144         perm.info.requestRes = sa.getResourceId(
   3145                 com.android.internal.R.styleable.AndroidManifestPermission_request, 0);
   3146 
   3147         perm.info.protectionLevel = sa.getInt(
   3148                 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
   3149                 PermissionInfo.PROTECTION_NORMAL);
   3150 
   3151         perm.info.flags = sa.getInt(
   3152                 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
   3153 
   3154         sa.recycle();
   3155 
   3156         if (perm.info.protectionLevel == -1) {
   3157             outError[0] = "<permission> does not specify protectionLevel";
   3158             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3159             return false;
   3160         }
   3161 
   3162         perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
   3163 
   3164         if (perm.info.getProtectionFlags() != 0) {
   3165             if ( (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_INSTANT) == 0
   3166                     && (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0
   3167                     && (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
   3168                     PermissionInfo.PROTECTION_SIGNATURE) {
   3169                 outError[0] = "<permission>  protectionLevel specifies a non-instant flag but is "
   3170                         + "not based on signature type";
   3171                 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3172                 return false;
   3173             }
   3174         }
   3175 
   3176         if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
   3177             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3178             return false;
   3179         }
   3180 
   3181         owner.permissions.add(perm);
   3182 
   3183         return true;
   3184     }
   3185 
   3186     private boolean parsePermissionTree(Package owner, Resources res,
   3187             XmlResourceParser parser, String[] outError)
   3188         throws XmlPullParserException, IOException {
   3189         Permission perm = new Permission(owner);
   3190 
   3191         TypedArray sa = res.obtainAttributes(parser,
   3192                 com.android.internal.R.styleable.AndroidManifestPermissionTree);
   3193 
   3194         if (!parsePackageItemInfo(owner, perm.info, outError,
   3195                 "<permission-tree>", sa, true /*nameRequired*/,
   3196                 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
   3197                 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
   3198                 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
   3199                 com.android.internal.R.styleable.AndroidManifestPermissionTree_roundIcon,
   3200                 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
   3201                 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
   3202             sa.recycle();
   3203             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3204             return false;
   3205         }
   3206 
   3207         sa.recycle();
   3208 
   3209         int index = perm.info.name.indexOf('.');
   3210         if (index > 0) {
   3211             index = perm.info.name.indexOf('.', index+1);
   3212         }
   3213         if (index < 0) {
   3214             outError[0] = "<permission-tree> name has less than three segments: "
   3215                 + perm.info.name;
   3216             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3217             return false;
   3218         }
   3219 
   3220         perm.info.descriptionRes = 0;
   3221         perm.info.requestRes = 0;
   3222         perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
   3223         perm.tree = true;
   3224 
   3225         if (!parseAllMetaData(res, parser, "<permission-tree>", perm,
   3226                 outError)) {
   3227             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3228             return false;
   3229         }
   3230 
   3231         owner.permissions.add(perm);
   3232 
   3233         return true;
   3234     }
   3235 
   3236     private Instrumentation parseInstrumentation(Package owner, Resources res,
   3237             XmlResourceParser parser, String[] outError)
   3238             throws XmlPullParserException, IOException {
   3239         TypedArray sa = res.obtainAttributes(parser,
   3240                 com.android.internal.R.styleable.AndroidManifestInstrumentation);
   3241 
   3242         if (mParseInstrumentationArgs == null) {
   3243             mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
   3244                     com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
   3245                     com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
   3246                     com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
   3247                     com.android.internal.R.styleable.AndroidManifestInstrumentation_roundIcon,
   3248                     com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
   3249                     com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
   3250             mParseInstrumentationArgs.tag = "<instrumentation>";
   3251         }
   3252 
   3253         mParseInstrumentationArgs.sa = sa;
   3254 
   3255         Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
   3256                 new InstrumentationInfo());
   3257         if (outError[0] != null) {
   3258             sa.recycle();
   3259             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3260             return null;
   3261         }
   3262 
   3263         String str;
   3264         // Note: don't allow this value to be a reference to a resource
   3265         // that may change.
   3266         str = sa.getNonResourceString(
   3267                 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
   3268         a.info.targetPackage = str != null ? str.intern() : null;
   3269 
   3270         str = sa.getNonResourceString(
   3271                 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetProcesses);
   3272         a.info.targetProcesses = str != null ? str.intern() : null;
   3273 
   3274         a.info.handleProfiling = sa.getBoolean(
   3275                 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
   3276                 false);
   3277 
   3278         a.info.functionalTest = sa.getBoolean(
   3279                 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
   3280                 false);
   3281 
   3282         sa.recycle();
   3283 
   3284         if (a.info.targetPackage == null) {
   3285             outError[0] = "<instrumentation> does not specify targetPackage";
   3286             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3287             return null;
   3288         }
   3289 
   3290         if (!parseAllMetaData(res, parser, "<instrumentation>", a,
   3291                 outError)) {
   3292             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3293             return null;
   3294         }
   3295 
   3296         owner.instrumentation.add(a);
   3297 
   3298         return a;
   3299     }
   3300 
   3301     /**
   3302      * Parse the {@code application} XML tree at the current parse location in a
   3303      * <em>base APK</em> manifest.
   3304      * <p>
   3305      * When adding new features, carefully consider if they should also be
   3306      * supported by split APKs.
   3307      */
   3308     private boolean parseBaseApplication(Package owner, Resources res,
   3309             XmlResourceParser parser, int flags, String[] outError)
   3310         throws XmlPullParserException, IOException {
   3311         final ApplicationInfo ai = owner.applicationInfo;
   3312         final String pkgName = owner.applicationInfo.packageName;
   3313 
   3314         TypedArray sa = res.obtainAttributes(parser,
   3315                 com.android.internal.R.styleable.AndroidManifestApplication);
   3316 
   3317         if (!parsePackageItemInfo(owner, ai, outError,
   3318                 "<application>", sa, false /*nameRequired*/,
   3319                 com.android.internal.R.styleable.AndroidManifestApplication_name,
   3320                 com.android.internal.R.styleable.AndroidManifestApplication_label,
   3321                 com.android.internal.R.styleable.AndroidManifestApplication_icon,
   3322                 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon,
   3323                 com.android.internal.R.styleable.AndroidManifestApplication_logo,
   3324                 com.android.internal.R.styleable.AndroidManifestApplication_banner)) {
   3325             sa.recycle();
   3326             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3327             return false;
   3328         }
   3329 
   3330         if (ai.name != null) {
   3331             ai.className = ai.name;
   3332         }
   3333 
   3334         String manageSpaceActivity = sa.getNonConfigurationString(
   3335                 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
   3336                 Configuration.NATIVE_CONFIG_VERSION);
   3337         if (manageSpaceActivity != null) {
   3338             ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
   3339                     outError);
   3340         }
   3341 
   3342         boolean allowBackup = sa.getBoolean(
   3343                 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
   3344         if (allowBackup) {
   3345             ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
   3346 
   3347             // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
   3348             // and restoreAnyVersion are only relevant if backup is possible for the
   3349             // given application.
   3350             String backupAgent = sa.getNonConfigurationString(
   3351                     com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
   3352                     Configuration.NATIVE_CONFIG_VERSION);
   3353             if (backupAgent != null) {
   3354                 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
   3355                 if (DEBUG_BACKUP) {
   3356                     Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
   3357                             + " from " + pkgName + "+" + backupAgent);
   3358                 }
   3359 
   3360                 if (sa.getBoolean(
   3361                         com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
   3362                         true)) {
   3363                     ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
   3364                 }
   3365                 if (sa.getBoolean(
   3366                         com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
   3367                         false)) {
   3368                     ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
   3369                 }
   3370                 if (sa.getBoolean(
   3371                         com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
   3372                         false)) {
   3373                     ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
   3374                 }
   3375                 if (sa.getBoolean(
   3376                         com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
   3377                         false)) {
   3378                     ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
   3379                 }
   3380             }
   3381 
   3382             TypedValue v = sa.peekValue(
   3383                     com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
   3384             if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
   3385                 if (DEBUG_BACKUP) {
   3386                     Slog.v(TAG, "fullBackupContent specified as boolean=" +
   3387                             (v.data == 0 ? "false" : "true"));
   3388                 }
   3389                 // "false" => -1, "true" => 0
   3390                 ai.fullBackupContent = (v.data == 0 ? -1 : 0);
   3391             }
   3392             if (DEBUG_BACKUP) {
   3393                 Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
   3394             }
   3395         }
   3396 
   3397         ai.theme = sa.getResourceId(
   3398                 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
   3399         ai.descriptionRes = sa.getResourceId(
   3400                 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
   3401 
   3402         if (sa.getBoolean(
   3403                 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
   3404                 false)) {
   3405             // Check if persistence is based on a feature being present
   3406             final String requiredFeature = sa.getNonResourceString(com.android.internal.R.styleable
   3407                     .AndroidManifestApplication_persistentWhenFeatureAvailable);
   3408             if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
   3409                 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
   3410             }
   3411         }
   3412 
   3413         if (sa.getBoolean(
   3414                 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
   3415                 false)) {
   3416             owner.mRequiredForAllUsers = true;
   3417         }
   3418 
   3419         String restrictedAccountType = sa.getString(com.android.internal.R.styleable
   3420                 .AndroidManifestApplication_restrictedAccountType);
   3421         if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
   3422             owner.mRestrictedAccountType = restrictedAccountType;
   3423         }
   3424 
   3425         String requiredAccountType = sa.getString(com.android.internal.R.styleable
   3426                 .AndroidManifestApplication_requiredAccountType);
   3427         if (requiredAccountType != null && requiredAccountType.length() > 0) {
   3428             owner.mRequiredAccountType = requiredAccountType;
   3429         }
   3430 
   3431         if (sa.getBoolean(
   3432                 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
   3433                 false)) {
   3434             ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
   3435         }
   3436 
   3437         if (sa.getBoolean(
   3438                 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
   3439                 false)) {
   3440             ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
   3441         }
   3442 
   3443         owner.baseHardwareAccelerated = sa.getBoolean(
   3444                 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
   3445                 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
   3446         if (owner.baseHardwareAccelerated) {
   3447             ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
   3448         }
   3449 
   3450         if (sa.getBoolean(
   3451                 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
   3452                 true)) {
   3453             ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
   3454         }
   3455 
   3456         if (sa.getBoolean(
   3457                 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
   3458                 false)) {
   3459             ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
   3460         }
   3461 
   3462         if (sa.getBoolean(
   3463                 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
   3464                 true)) {
   3465             ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
   3466         }
   3467 
   3468         // The parent package controls installation, hence specify test only installs.
   3469         if (owner.parentPackage == null) {
   3470             if (sa.getBoolean(
   3471                     com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
   3472                     false)) {
   3473                 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
   3474             }
   3475         }
   3476 
   3477         if (sa.getBoolean(
   3478                 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
   3479                 false)) {
   3480             ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
   3481         }
   3482 
   3483         if (sa.getBoolean(
   3484                 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
   3485                 owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.P)) {
   3486             ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
   3487         }
   3488 
   3489         if (sa.getBoolean(
   3490                 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
   3491                 false /* default is no RTL support*/)) {
   3492             ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
   3493         }
   3494 
   3495         if (sa.getBoolean(
   3496                 com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
   3497                 false)) {
   3498             ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
   3499         }
   3500 
   3501         if (sa.getBoolean(
   3502                 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
   3503                 true)) {
   3504             ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
   3505         }
   3506 
   3507         if (sa.getBoolean(
   3508                 R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
   3509                 false)) {
   3510             ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
   3511         }
   3512         if (sa.getBoolean(
   3513                 R.styleable.AndroidManifestApplication_directBootAware,
   3514                 false)) {
   3515             ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
   3516         }
   3517 
   3518         if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
   3519             if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) {
   3520                 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
   3521             } else {
   3522                 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
   3523             }
   3524         } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
   3525             ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
   3526         }
   3527 
   3528         ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
   3529 
   3530         ai.networkSecurityConfigRes = sa.getResourceId(
   3531                 com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig,
   3532                 0);
   3533         ai.category = sa.getInt(
   3534                 com.android.internal.R.styleable.AndroidManifestApplication_appCategory,
   3535                 ApplicationInfo.CATEGORY_UNDEFINED);
   3536 
   3537         String str;
   3538         str = sa.getNonConfigurationString(
   3539                 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
   3540         ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
   3541 
   3542         if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
   3543             str = sa.getNonConfigurationString(
   3544                     com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
   3545                     Configuration.NATIVE_CONFIG_VERSION);
   3546         } else {
   3547             // Some older apps have been seen to use a resource reference
   3548             // here that on older builds was ignored (with a warning).  We
   3549             // need to continue to do this for them so they don't break.
   3550             str = sa.getNonResourceString(
   3551                     com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
   3552         }
   3553         ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
   3554                 str, outError);
   3555         String factory = sa.getNonResourceString(
   3556                 com.android.internal.R.styleable.AndroidManifestApplication_appComponentFactory);
   3557         if (factory != null) {
   3558             ai.appComponentFactory = buildClassName(ai.packageName, factory, outError);
   3559         }
   3560 
   3561         if (outError[0] == null) {
   3562             CharSequence pname;
   3563             if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
   3564                 pname = sa.getNonConfigurationString(
   3565                         com.android.internal.R.styleable.AndroidManifestApplication_process,
   3566                         Configuration.NATIVE_CONFIG_VERSION);
   3567             } else {
   3568                 // Some older apps have been seen to use a resource reference
   3569                 // here that on older builds was ignored (with a warning).  We
   3570                 // need to continue to do this for them so they don't break.
   3571                 pname = sa.getNonResourceString(
   3572                         com.android.internal.R.styleable.AndroidManifestApplication_process);
   3573             }
   3574             ai.processName = buildProcessName(ai.packageName, null, pname,
   3575                     flags, mSeparateProcesses, outError);
   3576 
   3577             ai.enabled = sa.getBoolean(
   3578                     com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
   3579 
   3580             if (sa.getBoolean(
   3581                     com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
   3582                 ai.flags |= ApplicationInfo.FLAG_IS_GAME;
   3583             }
   3584 
   3585             if (sa.getBoolean(
   3586                     com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
   3587                     false)) {
   3588                 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
   3589 
   3590                 // A heavy-weight application can not be in a custom process.
   3591                 // We can do direct compare because we intern all strings.
   3592                 if (ai.processName != null && !ai.processName.equals(ai.packageName)) {
   3593                     outError[0] = "cantSaveState applications can not use custom processes";
   3594                 }
   3595             }
   3596         }
   3597 
   3598         ai.uiOptions = sa.getInt(
   3599                 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
   3600 
   3601         ai.classLoaderName = sa.getString(
   3602             com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
   3603         if (ai.classLoaderName != null
   3604                 && !ClassLoaderFactory.isValidClassLoaderName(ai.classLoaderName)) {
   3605             outError[0] = "Invalid class loader name: " + ai.classLoaderName;
   3606         }
   3607 
   3608         sa.recycle();
   3609 
   3610         if (outError[0] != null) {
   3611             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3612             return false;
   3613         }
   3614 
   3615         final int innerDepth = parser.getDepth();
   3616         // IMPORTANT: These must only be cached for a single <application> to avoid components
   3617         // getting added to the wrong package.
   3618         final CachedComponentArgs cachedArgs = new CachedComponentArgs();
   3619         int type;
   3620         boolean hasActivityOrder = false;
   3621         boolean hasReceiverOrder = false;
   3622         boolean hasServiceOrder = false;
   3623         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
   3624                 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
   3625             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   3626                 continue;
   3627             }
   3628 
   3629             String tagName = parser.getName();
   3630             if (tagName.equals("activity")) {
   3631                 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
   3632                         owner.baseHardwareAccelerated);
   3633                 if (a == null) {
   3634                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3635                     return false;
   3636                 }
   3637 
   3638                 hasActivityOrder |= (a.order != 0);
   3639                 owner.activities.add(a);
   3640 
   3641             } else if (tagName.equals("receiver")) {
   3642                 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
   3643                         true, false);
   3644                 if (a == null) {
   3645                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3646                     return false;
   3647                 }
   3648 
   3649                 hasReceiverOrder |= (a.order != 0);
   3650                 owner.receivers.add(a);
   3651 
   3652             } else if (tagName.equals("service")) {
   3653                 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
   3654                 if (s == null) {
   3655                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3656                     return false;
   3657                 }
   3658 
   3659                 hasServiceOrder |= (s.order != 0);
   3660                 owner.services.add(s);
   3661 
   3662             } else if (tagName.equals("provider")) {
   3663                 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
   3664                 if (p == null) {
   3665                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3666                     return false;
   3667                 }
   3668 
   3669                 owner.providers.add(p);
   3670 
   3671             } else if (tagName.equals("activity-alias")) {
   3672                 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
   3673                 if (a == null) {
   3674                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3675                     return false;
   3676                 }
   3677 
   3678                 hasActivityOrder |= (a.order != 0);
   3679                 owner.activities.add(a);
   3680 
   3681             } else if (parser.getName().equals("meta-data")) {
   3682                 // note: application meta-data is stored off to the side, so it can
   3683                 // remain null in the primary copy (we like to avoid extra copies because
   3684                 // it can be large)
   3685                 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
   3686                         outError)) == null) {
   3687                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3688                     return false;
   3689                 }
   3690             } else if (tagName.equals("static-library")) {
   3691                 sa = res.obtainAttributes(parser,
   3692                         com.android.internal.R.styleable.AndroidManifestStaticLibrary);
   3693 
   3694                 // Note: don't allow this value to be a reference to a resource
   3695                 // that may change.
   3696                 final String lname = sa.getNonResourceString(
   3697                         com.android.internal.R.styleable.AndroidManifestStaticLibrary_name);
   3698                 final int version = sa.getInt(
   3699                         com.android.internal.R.styleable.AndroidManifestStaticLibrary_version, -1);
   3700                 final int versionMajor = sa.getInt(
   3701                         com.android.internal.R.styleable.AndroidManifestStaticLibrary_versionMajor,
   3702                         0);
   3703 
   3704                 sa.recycle();
   3705 
   3706                 // Since the app canot run without a static lib - fail if malformed
   3707                 if (lname == null || version < 0) {
   3708                     outError[0] = "Bad static-library declaration name: " + lname
   3709                             + " version: " + version;
   3710                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3711                     XmlUtils.skipCurrentTag(parser);
   3712                     return false;
   3713                 }
   3714 
   3715                 if (owner.mSharedUserId != null) {
   3716                     outError[0] = "sharedUserId not allowed in static shared library";
   3717                     mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
   3718                     XmlUtils.skipCurrentTag(parser);
   3719                     return false;
   3720                 }
   3721 
   3722                 if (owner.staticSharedLibName != null) {
   3723                     outError[0] = "Multiple static-shared libs for package " + pkgName;
   3724                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3725                     XmlUtils.skipCurrentTag(parser);
   3726                     return false;
   3727                 }
   3728 
   3729                 owner.staticSharedLibName = lname.intern();
   3730                 if (version >= 0) {
   3731                     owner.staticSharedLibVersion =
   3732                             PackageInfo.composeLongVersionCode(versionMajor, version);
   3733                 } else {
   3734                     owner.staticSharedLibVersion = version;
   3735                 }
   3736                 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY;
   3737 
   3738                 XmlUtils.skipCurrentTag(parser);
   3739 
   3740             } else if (tagName.equals("library")) {
   3741                 sa = res.obtainAttributes(parser,
   3742                         com.android.internal.R.styleable.AndroidManifestLibrary);
   3743 
   3744                 // Note: don't allow this value to be a reference to a resource
   3745                 // that may change.
   3746                 String lname = sa.getNonResourceString(
   3747                         com.android.internal.R.styleable.AndroidManifestLibrary_name);
   3748 
   3749                 sa.recycle();
   3750 
   3751                 if (lname != null) {
   3752                     lname = lname.intern();
   3753                     if (!ArrayUtils.contains(owner.libraryNames, lname)) {
   3754                         owner.libraryNames = ArrayUtils.add(
   3755                                 owner.libraryNames, lname);
   3756                     }
   3757                 }
   3758 
   3759                 XmlUtils.skipCurrentTag(parser);
   3760 
   3761             } else if (tagName.equals("uses-static-library")) {
   3762                 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
   3763                     return false;
   3764                 }
   3765 
   3766             } else if (tagName.equals("uses-library")) {
   3767                 sa = res.obtainAttributes(parser,
   3768                         com.android.internal.R.styleable.AndroidManifestUsesLibrary);
   3769 
   3770                 // Note: don't allow this value to be a reference to a resource
   3771                 // that may change.
   3772                 String lname = sa.getNonResourceString(
   3773                         com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
   3774                 boolean req = sa.getBoolean(
   3775                         com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
   3776                         true);
   3777 
   3778                 sa.recycle();
   3779 
   3780                 if (lname != null) {
   3781                     lname = lname.intern();
   3782                     if (req) {
   3783                         owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
   3784                     } else {
   3785                         owner.usesOptionalLibraries = ArrayUtils.add(
   3786                                 owner.usesOptionalLibraries, lname);
   3787                     }
   3788                 }
   3789 
   3790                 XmlUtils.skipCurrentTag(parser);
   3791 
   3792             } else if (tagName.equals("uses-package")) {
   3793                 // Dependencies for app installers; we don't currently try to
   3794                 // enforce this.
   3795                 XmlUtils.skipCurrentTag(parser);
   3796 
   3797             } else {
   3798                 if (!RIGID_PARSER) {
   3799                     Slog.w(TAG, "Unknown element under <application>: " + tagName
   3800                             + " at " + mArchiveSourcePath + " "
   3801                             + parser.getPositionDescription());
   3802                     XmlUtils.skipCurrentTag(parser);
   3803                     continue;
   3804                 } else {
   3805                     outError[0] = "Bad element under <application>: " + tagName;
   3806                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3807                     return false;
   3808                 }
   3809             }
   3810         }
   3811 
   3812         if (hasActivityOrder) {
   3813             Collections.sort(owner.activities, (a1, a2) -> Integer.compare(a2.order, a1.order));
   3814         }
   3815         if (hasReceiverOrder) {
   3816             Collections.sort(owner.receivers,  (r1, r2) -> Integer.compare(r2.order, r1.order));
   3817         }
   3818         if (hasServiceOrder) {
   3819             Collections.sort(owner.services,  (s1, s2) -> Integer.compare(s2.order, s1.order));
   3820         }
   3821         // Must be ran after the entire {@link ApplicationInfo} has been fully processed and after
   3822         // every activity info has had a chance to set it from its attributes.
   3823         setMaxAspectRatio(owner);
   3824 
   3825         PackageBackwardCompatibility.modifySharedLibraries(owner);
   3826 
   3827         if (hasDomainURLs(owner)) {
   3828             owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
   3829         } else {
   3830             owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
   3831         }
   3832 
   3833         return true;
   3834     }
   3835 
   3836     /**
   3837      * Check if one of the IntentFilter as both actions DEFAULT / VIEW and a HTTP/HTTPS data URI
   3838      */
   3839     private static boolean hasDomainURLs(Package pkg) {
   3840         if (pkg == null || pkg.activities == null) return false;
   3841         final ArrayList<Activity> activities = pkg.activities;
   3842         final int countActivities = activities.size();
   3843         for (int n=0; n<countActivities; n++) {
   3844             Activity activity = activities.get(n);
   3845             ArrayList<ActivityIntentInfo> filters = activity.intents;
   3846             if (filters == null) continue;
   3847             final int countFilters = filters.size();
   3848             for (int m=0; m<countFilters; m++) {
   3849                 ActivityIntentInfo aii = filters.get(m);
   3850                 if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
   3851                 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
   3852                 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
   3853                         aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
   3854                     return true;
   3855                 }
   3856             }
   3857         }
   3858         return false;
   3859     }
   3860 
   3861     /**
   3862      * Parse the {@code application} XML tree at the current parse location in a
   3863      * <em>split APK</em> manifest.
   3864      * <p>
   3865      * Note that split APKs have many more restrictions on what they're capable
   3866      * of doing, so many valid features of a base APK have been carefully
   3867      * omitted here.
   3868      */
   3869     private boolean parseSplitApplication(Package owner, Resources res, XmlResourceParser parser,
   3870             int flags, int splitIndex, String[] outError)
   3871             throws XmlPullParserException, IOException {
   3872         TypedArray sa = res.obtainAttributes(parser,
   3873                 com.android.internal.R.styleable.AndroidManifestApplication);
   3874 
   3875         if (sa.getBoolean(
   3876                 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
   3877             owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
   3878         }
   3879 
   3880         final String classLoaderName = sa.getString(
   3881                 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
   3882         if (classLoaderName == null || ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) {
   3883             owner.applicationInfo.splitClassLoaderNames[splitIndex] = classLoaderName;
   3884         } else {
   3885             outError[0] = "Invalid class loader name: " + classLoaderName;
   3886             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3887             return false;
   3888         }
   3889 
   3890         final int innerDepth = parser.getDepth();
   3891         int type;
   3892         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
   3893                 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
   3894             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   3895                 continue;
   3896             }
   3897 
   3898             ComponentInfo parsedComponent = null;
   3899 
   3900             // IMPORTANT: These must only be cached for a single <application> to avoid components
   3901             // getting added to the wrong package.
   3902             final CachedComponentArgs cachedArgs = new CachedComponentArgs();
   3903             String tagName = parser.getName();
   3904             if (tagName.equals("activity")) {
   3905                 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
   3906                         owner.baseHardwareAccelerated);
   3907                 if (a == null) {
   3908                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3909                     return false;
   3910                 }
   3911 
   3912                 owner.activities.add(a);
   3913                 parsedComponent = a.info;
   3914 
   3915             } else if (tagName.equals("receiver")) {
   3916                 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
   3917                         true, false);
   3918                 if (a == null) {
   3919                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3920                     return false;
   3921                 }
   3922 
   3923                 owner.receivers.add(a);
   3924                 parsedComponent = a.info;
   3925 
   3926             } else if (tagName.equals("service")) {
   3927                 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
   3928                 if (s == null) {
   3929                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3930                     return false;
   3931                 }
   3932 
   3933                 owner.services.add(s);
   3934                 parsedComponent = s.info;
   3935 
   3936             } else if (tagName.equals("provider")) {
   3937                 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
   3938                 if (p == null) {
   3939                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3940                     return false;
   3941                 }
   3942 
   3943                 owner.providers.add(p);
   3944                 parsedComponent = p.info;
   3945 
   3946             } else if (tagName.equals("activity-alias")) {
   3947                 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
   3948                 if (a == null) {
   3949                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3950                     return false;
   3951                 }
   3952 
   3953                 owner.activities.add(a);
   3954                 parsedComponent = a.info;
   3955 
   3956             } else if (parser.getName().equals("meta-data")) {
   3957                 // note: application meta-data is stored off to the side, so it can
   3958                 // remain null in the primary copy (we like to avoid extra copies because
   3959                 // it can be large)
   3960                 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
   3961                         outError)) == null) {
   3962                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   3963                     return false;
   3964                 }
   3965 
   3966             } else if (tagName.equals("uses-static-library")) {
   3967                 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
   3968                     return false;
   3969                 }
   3970 
   3971             } else if (tagName.equals("uses-library")) {
   3972                 sa = res.obtainAttributes(parser,
   3973                         com.android.internal.R.styleable.AndroidManifestUsesLibrary);
   3974 
   3975                 // Note: don't allow this value to be a reference to a resource
   3976                 // that may change.
   3977                 String lname = sa.getNonResourceString(
   3978                         com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
   3979                 boolean req = sa.getBoolean(
   3980                         com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
   3981                         true);
   3982 
   3983                 sa.recycle();
   3984 
   3985                 if (lname != null) {
   3986                     lname = lname.intern();
   3987                     if (req) {
   3988                         // Upgrade to treat as stronger constraint
   3989                         owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
   3990                         owner.usesOptionalLibraries = ArrayUtils.remove(
   3991                                 owner.usesOptionalLibraries, lname);
   3992                     } else {
   3993                         // Ignore if someone already defined as required
   3994                         if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
   3995                             owner.usesOptionalLibraries = ArrayUtils.add(
   3996                                     owner.usesOptionalLibraries, lname);
   3997                         }
   3998                     }
   3999                 }
   4000 
   4001                 XmlUtils.skipCurrentTag(parser);
   4002 
   4003             } else if (tagName.equals("uses-package")) {
   4004                 // Dependencies for app installers; we don't currently try to
   4005                 // enforce this.
   4006                 XmlUtils.skipCurrentTag(parser);
   4007 
   4008             } else {
   4009                 if (!RIGID_PARSER) {
   4010                     Slog.w(TAG, "Unknown element under <application>: " + tagName
   4011                             + " at " + mArchiveSourcePath + " "
   4012                             + parser.getPositionDescription());
   4013                     XmlUtils.skipCurrentTag(parser);
   4014                     continue;
   4015                 } else {
   4016                     outError[0] = "Bad element under <application>: " + tagName;
   4017                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
   4018                     return false;
   4019                 }
   4020             }
   4021 
   4022             if (parsedComponent != null && parsedComponent.splitName == null) {
   4023                 // If the loaded component did not specify a split, inherit the split name
   4024                 // based on the split it is defined in.
   4025                 // This is used to later load the correct split when starting this
   4026                 // component.
   4027                 parsedComponent.splitName = owner.splitNames[splitIndex];
   4028             }
   4029         }
   4030 
   4031         return true;
   4032     }
   4033 
   4034     private static boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
   4035             String[] outError, String tag, TypedArray sa, boolean nameRequired,
   4036             int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) {
   4037         // This case can only happen in unit tests where we sometimes need to create fakes
   4038         // of various package parser data structures.
   4039         if (sa == null) {
   4040             outError[0] = tag + " does not contain any attributes";
   4041             return false;
   4042         }
   4043 
   4044         String name = sa.getNonConfigurationString(nameRes, 0);
   4045         if (name == null) {
   4046             if (nameRequired) {
   4047                 outError[0] = tag + " does not specify android:name";
   4048                 return false;
   4049             }
   4050         } else {
   4051             outInfo.name
   4052                 = buildClassName(owner.applicationInfo.packageName, name, outError);
   4053             if (outInfo.name == null) {
   4054                 return false;
   4055             }
   4056         }
   4057 
   4058         final boolean useRoundIcon =
   4059                 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
   4060         int roundIconVal = useRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
   4061         if (roundIconVal != 0) {
   4062             outInfo.icon = roundIconVal;
   4063             outInfo.nonLocalizedLabel = null;
   4064         } else {
   4065             int iconVal = sa.getResourceId(iconRes, 0);
   4066             if (iconVal != 0) {
   4067                 outInfo.icon = iconVal;
   4068                 outInfo.nonLocalizedLabel = null;
   4069             }
   4070         }
   4071 
   4072         int logoVal = sa.getResourceId(logoRes, 0);
   4073         if (logoVal != 0) {
   4074             outInfo.logo = logoVal;
   4075         }
   4076 
   4077         int bannerVal = sa.getResourceId(bannerRes, 0);
   4078         if (bannerVal != 0) {
   4079             outInfo.banner = bannerVal;
   4080         }
   4081 
   4082         TypedValue v = sa.peekValue(labelRes);
   4083         if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
   4084             outInfo.nonLocalizedLabel = v.coerceToString();
   4085         }
   4086 
   4087         outInfo.packageName = owner.packageName;
   4088 
   4089         return true;
   4090     }
   4091 
   4092     private Activity parseActivity(Package owner, Resources res,
   4093             XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs,
   4094             boolean receiver, boolean hardwareAccelerated)
   4095             throws XmlPullParserException, IOException {
   4096         TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
   4097 
   4098         if (cachedArgs.mActivityArgs == null) {
   4099             cachedArgs.mActivityArgs = new ParseComponentArgs(owner, outError,
   4100                     R.styleable.AndroidManifestActivity_name,
   4101                     R.styleable.AndroidManifestActivity_label,
   4102                     R.styleable.AndroidManifestActivity_icon,
   4103                     R.styleable.AndroidManifestActivity_roundIcon,
   4104                     R.styleable.AndroidManifestActivity_logo,
   4105                     R.styleable.AndroidManifestActivity_banner,
   4106                     mSeparateProcesses,
   4107                     R.styleable.AndroidManifestActivity_process,
   4108                     R.styleable.AndroidManifestActivity_description,
   4109                     R.styleable.AndroidManifestActivity_enabled);
   4110         }
   4111 
   4112         cachedArgs.mActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
   4113         cachedArgs.mActivityArgs.sa = sa;
   4114         cachedArgs.mActivityArgs.flags = flags;
   4115 
   4116         Activity a = new Activity(cachedArgs.mActivityArgs, new ActivityInfo());
   4117         if (outError[0] != null) {
   4118             sa.recycle();
   4119             return null;
   4120         }
   4121 
   4122         boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
   4123         if (setExported) {
   4124             a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
   4125         }
   4126 
   4127         a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
   4128 
   4129         a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
   4130                 a.info.applicationInfo.uiOptions);
   4131 
   4132         String parentName = sa.getNonConfigurationString(
   4133                 R.styleable.AndroidManifestActivity_parentActivityName,
   4134                 Configuration.NATIVE_CONFIG_VERSION);
   4135         if (parentName != null) {
   4136             String parentClassName = buildClassName(a.info.packageName, parentName, outError);
   4137             if (outError[0] == null) {
   4138                 a.info.parentActivityName = parentClassName;
   4139             } else {
   4140                 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
   4141                         parentName);
   4142                 outError[0] = null;
   4143             }
   4144         }
   4145 
   4146         String str;
   4147         str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
   4148         if (str == null) {
   4149             a.info.permission = owner.applicationInfo.permission;
   4150         } else {
   4151             a.info.permission = str.length() > 0 ? str.toString().intern() : null;
   4152         }
   4153 
   4154         str = sa.getNonConfigurationString(
   4155                 R.styleable.AndroidManifestActivity_taskAffinity,
   4156                 Configuration.NATIVE_CONFIG_VERSION);
   4157         a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
   4158                 owner.applicationInfo.taskAffinity, str, outError);
   4159 
   4160         a.info.splitName =
   4161                 sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_splitName, 0);
   4162 
   4163         a.info.flags = 0;
   4164         if (sa.getBoolean(
   4165                 R.styleable.AndroidManifestActivity_multiprocess, false)) {
   4166             a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
   4167         }
   4168 
   4169         if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
   4170             a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
   4171         }
   4172 
   4173         if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
   4174             a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
   4175         }
   4176 
   4177         if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
   4178             a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
   4179         }
   4180 
   4181         if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
   4182             a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
   4183         }
   4184 
   4185         if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
   4186             a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
   4187         }
   4188 
   4189         if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
   4190             a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
   4191         }
   4192 
   4193         if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
   4194                 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
   4195             a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
   4196         }
   4197 
   4198         if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
   4199             a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
   4200         }
   4201 
   4202         if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
   4203                 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
   4204             a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
   4205         }
   4206 
   4207         if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
   4208             a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
   4209         }
   4210 
   4211         if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
   4212             a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
   4213         }
   4214 
   4215         if (!receiver) {
   4216             if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
   4217                     hardwareAccelerated)) {
   4218                 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
   4219             }
   4220 
   4221             a.info.launchMode = sa.getInt(
   4222                     R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
   4223             a.info.documentLaunchMode = sa.getInt(
   4224                     R.styleable.AndroidManifestActivity_documentLaunchMode,
   4225                     ActivityInfo.DOCUMENT_LAUNCH_NONE);
   4226             a.info.maxRecents = sa.getInt(
   4227                     R.styleable.AndroidManifestActivity_maxRecents,
   4228                     ActivityManager.getDefaultAppRecentsLimitStatic());
   4229             a.info.configChanges = getActivityConfigChanges(
   4230                     sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
   4231                     sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0));
   4232             a.info.softInputMode = sa.getInt(
   4233                     R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
   4234 
   4235             a.info.persistableMode = sa.getInteger(
   4236                     R.styleable.AndroidManifestActivity_persistableMode,
   4237                     ActivityInfo.PERSIST_ROOT_ONLY);
   4238 
   4239             if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
   4240                 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
   4241             }
   4242 
   4243             if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
   4244                 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
   4245             }
   4246 
   4247             if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
   4248                 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
   4249             }
   4250 
   4251             if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
   4252                 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
   4253             }
   4254 
   4255             a.info.screenOrientation = sa.getInt(
   4256                     R.styleable.AndroidManifestActivity_screenOrientation,
   4257                     SCREEN_ORIENTATION_UNSPECIFIED);
   4258 
   4259             setActivityResizeMode(a.info, sa, owner);
   4260 
   4261             if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
   4262                     false)) {
   4263                 a.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE;
   4264             }
   4265 
   4266             if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
   4267                 a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
   4268             }
   4269 
   4270             if (sa.hasValue(R.styleable.AndroidManifestActivity_maxAspectRatio)
   4271                     && sa.getType(R.styleable.AndroidManifestActivity_maxAspectRatio)
   4272                     == TypedValue.TYPE_FLOAT) {
   4273                 a.setMaxAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_maxAspectRatio,
   4274                         0 /*default*/));
   4275             }
   4276 
   4277             a.info.lockTaskLaunchMode =
   4278                     sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
   4279 
   4280             a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
   4281                     R.styleable.AndroidManifestActivity_directBootAware,
   4282                     false);
   4283 
   4284             a.info.requestedVrComponent =
   4285                 sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
   4286 
   4287             a.info.rotationAnimation =
   4288                 sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, ROTATION_ANIMATION_UNSPECIFIED);
   4289 
   4290             a.info.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode,
   4291                     ActivityInfo.COLOR_MODE_DEFAULT);
   4292 
   4293             if (sa.getBoolean(R.styleable.AndroidManifestActivity_showWhenLocked, false)) {
   4294                 a.info.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
   4295             }
   4296 
   4297             if (sa.getBoolean(R.styleable.AndroidManifestActivity_turnScreenOn, false)) {
   4298                 a.info.flags |= ActivityInfo.FLAG_TURN_SCREEN_ON;
   4299             }
   4300 
   4301         } else {
   4302             a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
   4303             a.info.configChanges = 0;
   4304 
   4305             if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
   4306                 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
   4307             }
   4308 
   4309             a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
   4310                     R.styleable.AndroidManifestActivity_directBootAware,
   4311                     false);
   4312         }
   4313 
   4314         if (a.info.directBootAware) {
   4315             owner.applicationInfo.privateFlags |=
   4316                     ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
   4317         }
   4318 
   4319         // can't make this final; we may set it later via meta-data
   4320         boolean visibleToEphemeral =
   4321                 sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
   4322         if (visibleToEphemeral) {
   4323             a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
   4324             owner.visibleToInstantApps = true;
   4325         }
   4326 
   4327         sa.recycle();
   4328 
   4329         if (receiver && (owner.applicationInfo.privateFlags
   4330                 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
   4331             // A heavy-weight application can not have receives in its main process
   4332             // We can do direct compare because we intern all strings.
   4333             if (a.info.processName == owner.packageName) {
   4334                 outError[0] = "Heavy-weight applications can not have receivers in main process";
   4335             }
   4336         }
   4337 
   4338         if (outError[0] != null) {
   4339             return null;
   4340         }
   4341 
   4342         int outerDepth = parser.getDepth();
   4343         int type;
   4344         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   4345                && (type != XmlPullParser.END_TAG
   4346                        || parser.getDepth() > outerDepth)) {
   4347             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   4348                 continue;
   4349             }
   4350 
   4351             if (parser.getName().equals("intent-filter")) {
   4352                 ActivityIntentInfo intent = new ActivityIntentInfo(a);
   4353                 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
   4354                         intent, outError)) {
   4355                     return null;
   4356                 }
   4357                 if (intent.countActions() == 0) {
   4358                     Slog.w(TAG, "No actions in intent filter at "
   4359                             + mArchiveSourcePath + " "
   4360                             + parser.getPositionDescription());
   4361                 } else {
   4362                     a.order = Math.max(intent.getOrder(), a.order);
   4363                     a.intents.add(intent);
   4364                 }
   4365                 // adjust activity flags when we implicitly expose it via a browsable filter
   4366                 final int visibility = visibleToEphemeral
   4367                         ? IntentFilter.VISIBILITY_EXPLICIT
   4368                         : !receiver && isImplicitlyExposedIntent(intent)
   4369                                 ? IntentFilter.VISIBILITY_IMPLICIT
   4370                                 : IntentFilter.VISIBILITY_NONE;
   4371                 intent.setVisibilityToInstantApp(visibility);
   4372                 if (intent.isVisibleToInstantApp()) {
   4373                     a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
   4374                 }
   4375                 if (intent.isImplicitlyVisibleToInstantApp()) {
   4376                     a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
   4377                 }
   4378                 if (LOG_UNSAFE_BROADCASTS && receiver
   4379                         && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
   4380                     for (int i = 0; i < intent.countActions(); i++) {
   4381                         final String action = intent.getAction(i);
   4382                         if (action == null || !action.startsWith("android.")) continue;
   4383                         if (!SAFE_BROADCASTS.contains(action)) {
   4384                             Slog.w(TAG, "Broadcast " + action + " may never be delivered to "
   4385                                     + owner.packageName + " as requested at: "
   4386                                     + parser.getPositionDescription());
   4387                         }
   4388                     }
   4389                 }
   4390             } else if (!receiver && parser.getName().equals("preferred")) {
   4391                 ActivityIntentInfo intent = new ActivityIntentInfo(a);
   4392                 if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/,
   4393                         intent, outError)) {
   4394                     return null;
   4395                 }
   4396                 if (intent.countActions() == 0) {
   4397                     Slog.w(TAG, "No actions in preferred at "
   4398                             + mArchiveSourcePath + " "
   4399                             + parser.getPositionDescription());
   4400                 } else {
   4401                     if (owner.preferredActivityFilters == null) {
   4402                         owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
   4403                     }
   4404                     owner.preferredActivityFilters.add(intent);
   4405                 }
   4406                 // adjust activity flags when we implicitly expose it via a browsable filter
   4407                 final int visibility = visibleToEphemeral
   4408                         ? IntentFilter.VISIBILITY_EXPLICIT
   4409                         : !receiver && isImplicitlyExposedIntent(intent)
   4410                                 ? IntentFilter.VISIBILITY_IMPLICIT
   4411                                 : IntentFilter.VISIBILITY_NONE;
   4412                 intent.setVisibilityToInstantApp(visibility);
   4413                 if (intent.isVisibleToInstantApp()) {
   4414                     a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
   4415                 }
   4416                 if (intent.isImplicitlyVisibleToInstantApp()) {
   4417                     a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
   4418                 }
   4419             } else if (parser.getName().equals("meta-data")) {
   4420                 if ((a.metaData = parseMetaData(res, parser, a.metaData,
   4421                         outError)) == null) {
   4422                     return null;
   4423                 }
   4424             } else if (!receiver && parser.getName().equals("layout")) {
   4425                 parseLayout(res, parser, a);
   4426             } else {
   4427                 if (!RIGID_PARSER) {
   4428                     Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
   4429                     if (receiver) {
   4430                         Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
   4431                                 + " at " + mArchiveSourcePath + " "
   4432                                 + parser.getPositionDescription());
   4433                     } else {
   4434                         Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
   4435                                 + " at " + mArchiveSourcePath + " "
   4436                                 + parser.getPositionDescription());
   4437                     }
   4438                     XmlUtils.skipCurrentTag(parser);
   4439                     continue;
   4440                 } else {
   4441                     if (receiver) {
   4442                         outError[0] = "Bad element under <receiver>: " + parser.getName();
   4443                     } else {
   4444                         outError[0] = "Bad element under <activity>: " + parser.getName();
   4445                     }
   4446                     return null;
   4447                 }
   4448             }
   4449         }
   4450 
   4451         if (!setExported) {
   4452             a.info.exported = a.intents.size() > 0;
   4453         }
   4454 
   4455         return a;
   4456     }
   4457 
   4458     private void setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package owner) {
   4459         final boolean appExplicitDefault = (owner.applicationInfo.privateFlags
   4460                 & (PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE
   4461                 | PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE)) != 0;
   4462 
   4463         if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity)
   4464                 || appExplicitDefault) {
   4465             // Activity or app explicitly set if it is resizeable or not;
   4466             final boolean appResizeable = (owner.applicationInfo.privateFlags
   4467                     & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE) != 0;
   4468             if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity,
   4469                     appResizeable)) {
   4470                 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE;
   4471             } else {
   4472                 aInfo.resizeMode = RESIZE_MODE_UNRESIZEABLE;
   4473             }
   4474             return;
   4475         }
   4476 
   4477         if ((owner.applicationInfo.privateFlags
   4478                 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) != 0) {
   4479             // The activity or app didn't explicitly set the resizing option, however we want to
   4480             // make it resize due to the sdk version it is targeting.
   4481             aInfo.resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
   4482             return;
   4483         }
   4484 
   4485         // resize preference isn't set and target sdk version doesn't support resizing apps by
   4486         // default. For the app to be resizeable if it isn't fixed orientation or immersive.
   4487         if (aInfo.isFixedOrientationPortrait()) {
   4488             aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
   4489         } else if (aInfo.isFixedOrientationLandscape()) {
   4490             aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
   4491         } else if (aInfo.isFixedOrientation()) {
   4492             aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
   4493         } else {
   4494             aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
   4495         }
   4496     }
   4497 
   4498     /**
   4499      * Sets every the max aspect ratio of every child activity that doesn't already have an aspect
   4500      * ratio set.
   4501      */
   4502     private void setMaxAspectRatio(Package owner) {
   4503         // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater.
   4504         // NOTE: 16.7:9 was the max aspect ratio Android devices can support pre-O per the CDD.
   4505         float maxAspectRatio = owner.applicationInfo.targetSdkVersion < O
   4506                 ? DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0;
   4507 
   4508         if (owner.applicationInfo.maxAspectRatio != 0) {
   4509             // Use the application max aspect ration as default if set.
   4510             maxAspectRatio = owner.applicationInfo.maxAspectRatio;
   4511         } else if (owner.mAppMetaData != null
   4512                 && owner.mAppMetaData.containsKey(METADATA_MAX_ASPECT_RATIO)) {
   4513             maxAspectRatio = owner.mAppMetaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio);
   4514         }
   4515 
   4516         for (Activity activity : owner.activities) {
   4517             // If the max aspect ratio for the activity has already been set, skip.
   4518             if (activity.hasMaxAspectRatio()) {
   4519                 continue;
   4520             }
   4521 
   4522             // By default we prefer to use a values defined on the activity directly than values
   4523             // defined on the application. We do not check the styled attributes on the activity
   4524             // as it would have already been set when we processed the activity. We wait to process
   4525             // the meta data here since this method is called at the end of processing the
   4526             // application and all meta data is guaranteed.
   4527             final float activityAspectRatio = activity.metaData != null
   4528                     ? activity.metaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio)
   4529                     : maxAspectRatio;
   4530 
   4531             activity.setMaxAspectRatio(activityAspectRatio);
   4532         }
   4533     }
   4534 
   4535     /**
   4536      * @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml.
   4537      * @param recreateOnConfigChanges The bit mask recreateOnConfigChanges fetched from
   4538      *                                AndroidManifest.xml.
   4539      * @hide Exposed for unit testing only.
   4540      */
   4541     @TestApi
   4542     public static int getActivityConfigChanges(int configChanges, int recreateOnConfigChanges) {
   4543         return configChanges | ((~recreateOnConfigChanges) & RECREATE_ON_CONFIG_CHANGES_MASK);
   4544     }
   4545 
   4546     private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
   4547         TypedArray sw = res.obtainAttributes(attrs,
   4548                 com.android.internal.R.styleable.AndroidManifestLayout);
   4549         int width = -1;
   4550         float widthFraction = -1f;
   4551         int height = -1;
   4552         float heightFraction = -1f;
   4553         final int widthType = sw.getType(
   4554                 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth);
   4555         if (widthType == TypedValue.TYPE_FRACTION) {
   4556             widthFraction = sw.getFraction(
   4557                     com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
   4558                     1, 1, -1);
   4559         } else if (widthType == TypedValue.TYPE_DIMENSION) {
   4560             width = sw.getDimensionPixelSize(
   4561                     com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
   4562                     -1);
   4563         }
   4564         final int heightType = sw.getType(
   4565                 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight);
   4566         if (heightType == TypedValue.TYPE_FRACTION) {
   4567             heightFraction = sw.getFraction(
   4568                     com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
   4569                     1, 1, -1);
   4570         } else if (heightType == TypedValue.TYPE_DIMENSION) {
   4571             height = sw.getDimensionPixelSize(
   4572                     com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
   4573                     -1);
   4574         }
   4575         int gravity = sw.getInt(
   4576                 com.android.internal.R.styleable.AndroidManifestLayout_gravity,
   4577                 Gravity.CENTER);
   4578         int minWidth = sw.getDimensionPixelSize(
   4579                 com.android.internal.R.styleable.AndroidManifestLayout_minWidth,
   4580                 -1);
   4581         int minHeight = sw.getDimensionPixelSize(
   4582                 com.android.internal.R.styleable.AndroidManifestLayout_minHeight,
   4583                 -1);
   4584         sw.recycle();
   4585         a.info.windowLayout = new ActivityInfo.WindowLayout(width, widthFraction,
   4586                 height, heightFraction, gravity, minWidth, minHeight);
   4587     }
   4588 
   4589     private Activity parseActivityAlias(Package owner, Resources res,
   4590             XmlResourceParser parser, int flags, String[] outError,
   4591             CachedComponentArgs cachedArgs)
   4592             throws XmlPullParserException, IOException {
   4593         TypedArray sa = res.obtainAttributes(parser,
   4594                 com.android.internal.R.styleable.AndroidManifestActivityAlias);
   4595 
   4596         String targetActivity = sa.getNonConfigurationString(
   4597                 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
   4598                 Configuration.NATIVE_CONFIG_VERSION);
   4599         if (targetActivity == null) {
   4600             outError[0] = "<activity-alias> does not specify android:targetActivity";
   4601             sa.recycle();
   4602             return null;
   4603         }
   4604 
   4605         targetActivity = buildClassName(owner.applicationInfo.packageName,
   4606                 targetActivity, outError);
   4607         if (targetActivity == null) {
   4608             sa.recycle();
   4609             return null;
   4610         }
   4611 
   4612         if (cachedArgs.mActivityAliasArgs == null) {
   4613             cachedArgs.mActivityAliasArgs = new ParseComponentArgs(owner, outError,
   4614                     com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
   4615                     com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
   4616                     com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
   4617                     com.android.internal.R.styleable.AndroidManifestActivityAlias_roundIcon,
   4618                     com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
   4619                     com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
   4620                     mSeparateProcesses,
   4621                     0,
   4622                     com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
   4623                     com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
   4624             cachedArgs.mActivityAliasArgs.tag = "<activity-alias>";
   4625         }
   4626 
   4627         cachedArgs.mActivityAliasArgs.sa = sa;
   4628         cachedArgs.mActivityAliasArgs.flags = flags;
   4629 
   4630         Activity target = null;
   4631 
   4632         final int NA = owner.activities.size();
   4633         for (int i=0; i<NA; i++) {
   4634             Activity t = owner.activities.get(i);
   4635             if (targetActivity.equals(t.info.name)) {
   4636                 target = t;
   4637                 break;
   4638             }
   4639         }
   4640 
   4641         if (target == null) {
   4642             outError[0] = "<activity-alias> target activity " + targetActivity
   4643                     + " not found in manifest";
   4644             sa.recycle();
   4645             return null;
   4646         }
   4647 
   4648         ActivityInfo info = new ActivityInfo();
   4649         info.targetActivity = targetActivity;
   4650         info.configChanges = target.info.configChanges;
   4651         info.flags = target.info.flags;
   4652         info.icon = target.info.icon;
   4653         info.logo = target.info.logo;
   4654         info.banner = target.info.banner;
   4655         info.labelRes = target.info.labelRes;
   4656         info.nonLocalizedLabel = target.info.nonLocalizedLabel;
   4657         info.launchMode = target.info.launchMode;
   4658         info.lockTaskLaunchMode = target.info.lockTaskLaunchMode;
   4659         info.processName = target.info.processName;
   4660         if (info.descriptionRes == 0) {
   4661             info.descriptionRes = target.info.descriptionRes;
   4662         }
   4663         info.screenOrientation = target.info.screenOrientation;
   4664         info.taskAffinity = target.info.taskAffinity;
   4665         info.theme = target.info.theme;
   4666         info.softInputMode = target.info.softInputMode;
   4667         info.uiOptions = target.info.uiOptions;
   4668         info.parentActivityName = target.info.parentActivityName;
   4669         info.maxRecents = target.info.maxRecents;
   4670         info.windowLayout = target.info.windowLayout;
   4671         info.resizeMode = target.info.resizeMode;
   4672         info.maxAspectRatio = target.info.maxAspectRatio;
   4673         info.requestedVrComponent = target.info.requestedVrComponent;
   4674 
   4675         info.encryptionAware = info.directBootAware = target.info.directBootAware;
   4676 
   4677         Activity a = new Activity(cachedArgs.mActivityAliasArgs, info);
   4678         if (outError[0] != null) {
   4679             sa.recycle();
   4680             return null;
   4681         }
   4682 
   4683         final boolean setExported = sa.hasValue(
   4684                 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
   4685         if (setExported) {
   4686             a.info.exported = sa.getBoolean(
   4687                     com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
   4688         }
   4689 
   4690         String str;
   4691         str = sa.getNonConfigurationString(
   4692                 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
   4693         if (str != null) {
   4694             a.info.permission = str.length() > 0 ? str.toString().intern() : null;
   4695         }
   4696 
   4697         String parentName = sa.getNonConfigurationString(
   4698                 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
   4699                 Configuration.NATIVE_CONFIG_VERSION);
   4700         if (parentName != null) {
   4701             String parentClassName = buildClassName(a.info.packageName, parentName, outError);
   4702             if (outError[0] == null) {
   4703                 a.info.parentActivityName = parentClassName;
   4704             } else {
   4705                 Log.e(TAG, "Activity alias " + a.info.name +
   4706                         " specified invalid parentActivityName " + parentName);
   4707                 outError[0] = null;
   4708             }
   4709         }
   4710 
   4711         // TODO add visibleToInstantApps attribute to activity alias
   4712         final boolean visibleToEphemeral =
   4713                 ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0);
   4714 
   4715         sa.recycle();
   4716 
   4717         if (outError[0] != null) {
   4718             return null;
   4719         }
   4720 
   4721         int outerDepth = parser.getDepth();
   4722         int type;
   4723         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   4724                && (type != XmlPullParser.END_TAG
   4725                        || parser.getDepth() > outerDepth)) {
   4726             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   4727                 continue;
   4728             }
   4729 
   4730             if (parser.getName().equals("intent-filter")) {
   4731                 ActivityIntentInfo intent = new ActivityIntentInfo(a);
   4732                 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
   4733                         intent, outError)) {
   4734                     return null;
   4735                 }
   4736                 if (intent.countActions() == 0) {
   4737                     Slog.w(TAG, "No actions in intent filter at "
   4738                             + mArchiveSourcePath + " "
   4739                             + parser.getPositionDescription());
   4740                 } else {
   4741                     a.order = Math.max(intent.getOrder(), a.order);
   4742                     a.intents.add(intent);
   4743                 }
   4744                 // adjust activity flags when we implicitly expose it via a browsable filter
   4745                 final int visibility = visibleToEphemeral
   4746                         ? IntentFilter.VISIBILITY_EXPLICIT
   4747                         : isImplicitlyExposedIntent(intent)
   4748                                 ? IntentFilter.VISIBILITY_IMPLICIT
   4749                                 : IntentFilter.VISIBILITY_NONE;
   4750                 intent.setVisibilityToInstantApp(visibility);
   4751                 if (intent.isVisibleToInstantApp()) {
   4752                     a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
   4753                 }
   4754                 if (intent.isImplicitlyVisibleToInstantApp()) {
   4755                     a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
   4756                 }
   4757             } else if (parser.getName().equals("meta-data")) {
   4758                 if ((a.metaData=parseMetaData(res, parser, a.metaData,
   4759                         outError)) == null) {
   4760                     return null;
   4761                 }
   4762             } else {
   4763                 if (!RIGID_PARSER) {
   4764                     Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
   4765                             + " at " + mArchiveSourcePath + " "
   4766                             + parser.getPositionDescription());
   4767                     XmlUtils.skipCurrentTag(parser);
   4768                     continue;
   4769                 } else {
   4770                     outError[0] = "Bad element under <activity-alias>: " + parser.getName();
   4771                     return null;
   4772                 }
   4773             }
   4774         }
   4775 
   4776         if (!setExported) {
   4777             a.info.exported = a.intents.size() > 0;
   4778         }
   4779 
   4780         return a;
   4781     }
   4782 
   4783     private Provider parseProvider(Package owner, Resources res,
   4784             XmlResourceParser parser, int flags, String[] outError,
   4785             CachedComponentArgs cachedArgs)
   4786             throws XmlPullParserException, IOException {
   4787         TypedArray sa = res.obtainAttributes(parser,
   4788                 com.android.internal.R.styleable.AndroidManifestProvider);
   4789 
   4790         if (cachedArgs.mProviderArgs == null) {
   4791             cachedArgs.mProviderArgs = new ParseComponentArgs(owner, outError,
   4792                     com.android.internal.R.styleable.AndroidManifestProvider_name,
   4793                     com.android.internal.R.styleable.AndroidManifestProvider_label,
   4794                     com.android.internal.R.styleable.AndroidManifestProvider_icon,
   4795                     com.android.internal.R.styleable.AndroidManifestProvider_roundIcon,
   4796                     com.android.internal.R.styleable.AndroidManifestProvider_logo,
   4797                     com.android.internal.R.styleable.AndroidManifestProvider_banner,
   4798                     mSeparateProcesses,
   4799                     com.android.internal.R.styleable.AndroidManifestProvider_process,
   4800                     com.android.internal.R.styleable.AndroidManifestProvider_description,
   4801                     com.android.internal.R.styleable.AndroidManifestProvider_enabled);
   4802             cachedArgs.mProviderArgs.tag = "<provider>";
   4803         }
   4804 
   4805         cachedArgs.mProviderArgs.sa = sa;
   4806         cachedArgs.mProviderArgs.flags = flags;
   4807 
   4808         Provider p = new Provider(cachedArgs.mProviderArgs, new ProviderInfo());
   4809         if (outError[0] != null) {
   4810             sa.recycle();
   4811             return null;
   4812         }
   4813 
   4814         boolean providerExportedDefault = false;
   4815 
   4816         if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
   4817             // For compatibility, applications targeting API level 16 or lower
   4818             // should have their content providers exported by default, unless they
   4819             // specify otherwise.
   4820             providerExportedDefault = true;
   4821         }
   4822 
   4823         p.info.exported = sa.getBoolean(
   4824                 com.android.internal.R.styleable.AndroidManifestProvider_exported,
   4825                 providerExportedDefault);
   4826 
   4827         String cpname = sa.getNonConfigurationString(
   4828                 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
   4829 
   4830         p.info.isSyncable = sa.getBoolean(
   4831                 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
   4832                 false);
   4833 
   4834         String permission = sa.getNonConfigurationString(
   4835                 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
   4836         String str = sa.getNonConfigurationString(
   4837                 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
   4838         if (str == null) {
   4839             str = permission;
   4840         }
   4841         if (str == null) {
   4842             p.info.readPermission = owner.applicationInfo.permission;
   4843         } else {
   4844             p.info.readPermission =
   4845                 str.length() > 0 ? str.toString().intern() : null;
   4846         }
   4847         str = sa.getNonConfigurationString(
   4848                 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
   4849         if (str == null) {
   4850             str = permission;
   4851         }
   4852         if (str == null) {
   4853             p.info.writePermission = owner.applicationInfo.permission;
   4854         } else {
   4855             p.info.writePermission =
   4856                 str.length() > 0 ? str.toString().intern() : null;
   4857         }
   4858 
   4859         p.info.grantUriPermissions = sa.getBoolean(
   4860                 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
   4861                 false);
   4862 
   4863         p.info.multiprocess = sa.getBoolean(
   4864                 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
   4865                 false);
   4866 
   4867         p.info.initOrder = sa.getInt(
   4868                 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
   4869                 0);
   4870 
   4871         p.info.splitName =
   4872                 sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_splitName, 0);
   4873 
   4874         p.info.flags = 0;
   4875 
   4876         if (sa.getBoolean(
   4877                 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
   4878                 false)) {
   4879             p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
   4880         }
   4881 
   4882         p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
   4883                 R.styleable.AndroidManifestProvider_directBootAware,
   4884                 false);
   4885         if (p.info.directBootAware) {
   4886             owner.applicationInfo.privateFlags |=
   4887                     ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
   4888         }
   4889 
   4890         final boolean visibleToEphemeral =
   4891                 sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
   4892         if (visibleToEphemeral) {
   4893             p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
   4894             owner.visibleToInstantApps = true;
   4895         }
   4896 
   4897         sa.recycle();
   4898 
   4899         if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
   4900                 != 0) {
   4901             // A heavy-weight application can not have providers in its main process
   4902             // We can do direct compare because we intern all strings.
   4903             if (p.info.processName == owner.packageName) {
   4904                 outError[0] = "Heavy-weight applications can not have providers in main process";
   4905                 return null;
   4906             }
   4907         }
   4908 
   4909         if (cpname == null) {
   4910             outError[0] = "<provider> does not include authorities attribute";
   4911             return null;
   4912         }
   4913         if (cpname.length() <= 0) {
   4914             outError[0] = "<provider> has empty authorities attribute";
   4915             return null;
   4916         }
   4917         p.info.authority = cpname.intern();
   4918 
   4919         if (!parseProviderTags(
   4920                 res, parser, visibleToEphemeral, p, outError)) {
   4921             return null;
   4922         }
   4923 
   4924         return p;
   4925     }
   4926 
   4927     private boolean parseProviderTags(Resources res, XmlResourceParser parser,
   4928             boolean visibleToEphemeral, Provider outInfo, String[] outError)
   4929                     throws XmlPullParserException, IOException {
   4930         int outerDepth = parser.getDepth();
   4931         int type;
   4932         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   4933                && (type != XmlPullParser.END_TAG
   4934                        || parser.getDepth() > outerDepth)) {
   4935             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   4936                 continue;
   4937             }
   4938 
   4939             if (parser.getName().equals("intent-filter")) {
   4940                 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
   4941                 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
   4942                         intent, outError)) {
   4943                     return false;
   4944                 }
   4945                 if (visibleToEphemeral) {
   4946                     intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
   4947                     outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
   4948                 }
   4949                 outInfo.order = Math.max(intent.getOrder(), outInfo.order);
   4950                 outInfo.intents.add(intent);
   4951 
   4952             } else if (parser.getName().equals("meta-data")) {
   4953                 if ((outInfo.metaData=parseMetaData(res, parser,
   4954                         outInfo.metaData, outError)) == null) {
   4955                     return false;
   4956                 }
   4957 
   4958             } else if (parser.getName().equals("grant-uri-permission")) {
   4959                 TypedArray sa = res.obtainAttributes(parser,
   4960                         com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
   4961 
   4962                 PatternMatcher pa = null;
   4963 
   4964                 String str = sa.getNonConfigurationString(
   4965                         com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
   4966                 if (str != null) {
   4967                     pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
   4968                 }
   4969 
   4970                 str = sa.getNonConfigurationString(
   4971                         com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
   4972                 if (str != null) {
   4973                     pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
   4974                 }
   4975 
   4976                 str = sa.getNonConfigurationString(
   4977                         com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
   4978                 if (str != null) {
   4979                     pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
   4980                 }
   4981 
   4982                 sa.recycle();
   4983 
   4984                 if (pa != null) {
   4985                     if (outInfo.info.uriPermissionPatterns == null) {
   4986                         outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
   4987                         outInfo.info.uriPermissionPatterns[0] = pa;
   4988                     } else {
   4989                         final int N = outInfo.info.uriPermissionPatterns.length;
   4990                         PatternMatcher[] newp = new PatternMatcher[N+1];
   4991                         System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
   4992                         newp[N] = pa;
   4993                         outInfo.info.uriPermissionPatterns = newp;
   4994                     }
   4995                     outInfo.info.grantUriPermissions = true;
   4996                 } else {
   4997                     if (!RIGID_PARSER) {
   4998                         Slog.w(TAG, "Unknown element under <path-permission>: "
   4999                                 + parser.getName() + " at " + mArchiveSourcePath + " "
   5000                                 + parser.getPositionDescription());
   5001                         XmlUtils.skipCurrentTag(parser);
   5002                         continue;
   5003                     } else {
   5004                         outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
   5005                         return false;
   5006                     }
   5007                 }
   5008                 XmlUtils.skipCurrentTag(parser);
   5009 
   5010             } else if (parser.getName().equals("path-permission")) {
   5011                 TypedArray sa = res.obtainAttributes(parser,
   5012                         com.android.internal.R.styleable.AndroidManifestPathPermission);
   5013 
   5014                 PathPermission pa = null;
   5015 
   5016                 String permission = sa.getNonConfigurationString(
   5017                         com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
   5018                 String readPermission = sa.getNonConfigurationString(
   5019                         com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
   5020                 if (readPermission == null) {
   5021                     readPermission = permission;
   5022                 }
   5023                 String writePermission = sa.getNonConfigurationString(
   5024                         com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
   5025                 if (writePermission == null) {
   5026                     writePermission = permission;
   5027                 }
   5028 
   5029                 boolean havePerm = false;
   5030                 if (readPermission != null) {
   5031                     readPermission = readPermission.intern();
   5032                     havePerm = true;
   5033                 }
   5034                 if (writePermission != null) {
   5035                     writePermission = writePermission.intern();
   5036                     havePerm = true;
   5037                 }
   5038 
   5039                 if (!havePerm) {
   5040                     if (!RIGID_PARSER) {
   5041                         Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
   5042                                 + parser.getName() + " at " + mArchiveSourcePath + " "
   5043                                 + parser.getPositionDescription());
   5044                         XmlUtils.skipCurrentTag(parser);
   5045                         continue;
   5046                     } else {
   5047                         outError[0] = "No readPermission or writePermssion for <path-permission>";
   5048                         return false;
   5049                     }
   5050                 }
   5051 
   5052                 String path = sa.getNonConfigurationString(
   5053                         com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
   5054                 if (path != null) {
   5055                     pa = new PathPermission(path,
   5056                             PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
   5057                 }
   5058 
   5059                 path = sa.getNonConfigurationString(
   5060                         com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
   5061                 if (path != null) {
   5062                     pa = new PathPermission(path,
   5063                             PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
   5064                 }
   5065 
   5066                 path = sa.getNonConfigurationString(
   5067                         com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
   5068                 if (path != null) {
   5069                     pa = new PathPermission(path,
   5070                             PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
   5071                 }
   5072 
   5073                 path = sa.getNonConfigurationString(
   5074                         com.android.internal.R.styleable.AndroidManifestPathPermission_pathAdvancedPattern, 0);
   5075                 if (path != null) {
   5076                     pa = new PathPermission(path,
   5077                             PatternMatcher.PATTERN_ADVANCED_GLOB, readPermission, writePermission);
   5078                 }
   5079 
   5080                 sa.recycle();
   5081 
   5082                 if (pa != null) {
   5083                     if (outInfo.info.pathPermissions == null) {
   5084                         outInfo.info.pathPermissions = new PathPermission[1];
   5085                         outInfo.info.pathPermissions[0] = pa;
   5086                     } else {
   5087                         final int N = outInfo.info.pathPermissions.length;
   5088                         PathPermission[] newp = new PathPermission[N+1];
   5089                         System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
   5090                         newp[N] = pa;
   5091                         outInfo.info.pathPermissions = newp;
   5092                     }
   5093                 } else {
   5094                     if (!RIGID_PARSER) {
   5095                         Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
   5096                                 + parser.getName() + " at " + mArchiveSourcePath + " "
   5097                                 + parser.getPositionDescription());
   5098                         XmlUtils.skipCurrentTag(parser);
   5099                         continue;
   5100                     }
   5101                     outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
   5102                     return false;
   5103                 }
   5104                 XmlUtils.skipCurrentTag(parser);
   5105 
   5106             } else {
   5107                 if (!RIGID_PARSER) {
   5108                     Slog.w(TAG, "Unknown element under <provider>: "
   5109                             + parser.getName() + " at " + mArchiveSourcePath + " "
   5110                             + parser.getPositionDescription());
   5111                     XmlUtils.skipCurrentTag(parser);
   5112                     continue;
   5113                 } else {
   5114                     outError[0] = "Bad element under <provider>: " + parser.getName();
   5115                     return false;
   5116                 }
   5117             }
   5118         }
   5119         return true;
   5120     }
   5121 
   5122     private Service parseService(Package owner, Resources res,
   5123             XmlResourceParser parser, int flags, String[] outError,
   5124             CachedComponentArgs cachedArgs)
   5125             throws XmlPullParserException, IOException {
   5126         TypedArray sa = res.obtainAttributes(parser,
   5127                 com.android.internal.R.styleable.AndroidManifestService);
   5128 
   5129         if (cachedArgs.mServiceArgs == null) {
   5130             cachedArgs.mServiceArgs = new ParseComponentArgs(owner, outError,
   5131                     com.android.internal.R.styleable.AndroidManifestService_name,
   5132                     com.android.internal.R.styleable.AndroidManifestService_label,
   5133                     com.android.internal.R.styleable.AndroidManifestService_icon,
   5134                     com.android.internal.R.styleable.AndroidManifestService_roundIcon,
   5135                     com.android.internal.R.styleable.AndroidManifestService_logo,
   5136                     com.android.internal.R.styleable.AndroidManifestService_banner,
   5137                     mSeparateProcesses,
   5138                     com.android.internal.R.styleable.AndroidManifestService_process,
   5139                     com.android.internal.R.styleable.AndroidManifestService_description,
   5140                     com.android.internal.R.styleable.AndroidManifestService_enabled);
   5141             cachedArgs.mServiceArgs.tag = "<service>";
   5142         }
   5143 
   5144         cachedArgs.mServiceArgs.sa = sa;
   5145         cachedArgs.mServiceArgs.flags = flags;
   5146 
   5147         Service s = new Service(cachedArgs.mServiceArgs, new ServiceInfo());
   5148         if (outError[0] != null) {
   5149             sa.recycle();
   5150             return null;
   5151         }
   5152 
   5153         boolean setExported = sa.hasValue(
   5154                 com.android.internal.R.styleable.AndroidManifestService_exported);
   5155         if (setExported) {
   5156             s.info.exported = sa.getBoolean(
   5157                     com.android.internal.R.styleable.AndroidManifestService_exported, false);
   5158         }
   5159 
   5160         String str = sa.getNonConfigurationString(
   5161                 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
   5162         if (str == null) {
   5163             s.info.permission = owner.applicationInfo.permission;
   5164         } else {
   5165             s.info.permission = str.length() > 0 ? str.toString().intern() : null;
   5166         }
   5167 
   5168         s.info.splitName =
   5169                 sa.getNonConfigurationString(R.styleable.AndroidManifestService_splitName, 0);
   5170 
   5171         s.info.flags = 0;
   5172         if (sa.getBoolean(
   5173                 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
   5174                 false)) {
   5175             s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
   5176         }
   5177         if (sa.getBoolean(
   5178                 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
   5179                 false)) {
   5180             s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
   5181         }
   5182         if (sa.getBoolean(
   5183                 com.android.internal.R.styleable.AndroidManifestService_externalService,
   5184                 false)) {
   5185             s.info.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE;
   5186         }
   5187         if (sa.getBoolean(
   5188                 com.android.internal.R.styleable.AndroidManifestService_singleUser,
   5189                 false)) {
   5190             s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
   5191         }
   5192 
   5193         s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
   5194                 R.styleable.AndroidManifestService_directBootAware,
   5195                 false);
   5196         if (s.info.directBootAware) {
   5197             owner.applicationInfo.privateFlags |=
   5198                     ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
   5199         }
   5200 
   5201         boolean visibleToEphemeral =
   5202                 sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
   5203         if (visibleToEphemeral) {
   5204             s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
   5205             owner.visibleToInstantApps = true;
   5206         }
   5207 
   5208         sa.recycle();
   5209 
   5210         if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
   5211                 != 0) {
   5212             // A heavy-weight application can not have services in its main process
   5213             // We can do direct compare because we intern all strings.
   5214             if (s.info.processName == owner.packageName) {
   5215                 outError[0] = "Heavy-weight applications can not have services in main process";
   5216                 return null;
   5217             }
   5218         }
   5219 
   5220         int outerDepth = parser.getDepth();
   5221         int type;
   5222         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   5223                && (type != XmlPullParser.END_TAG
   5224                        || parser.getDepth() > outerDepth)) {
   5225             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   5226                 continue;
   5227             }
   5228 
   5229             if (parser.getName().equals("intent-filter")) {
   5230                 ServiceIntentInfo intent = new ServiceIntentInfo(s);
   5231                 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
   5232                         intent, outError)) {
   5233                     return null;
   5234                 }
   5235                 if (visibleToEphemeral) {
   5236                     intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
   5237                     s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
   5238                 }
   5239                 s.order = Math.max(intent.getOrder(), s.order);
   5240                 s.intents.add(intent);
   5241             } else if (parser.getName().equals("meta-data")) {
   5242                 if ((s.metaData=parseMetaData(res, parser, s.metaData,
   5243                         outError)) == null) {
   5244                     return null;
   5245                 }
   5246             } else {
   5247                 if (!RIGID_PARSER) {
   5248                     Slog.w(TAG, "Unknown element under <service>: "
   5249                             + parser.getName() + " at " + mArchiveSourcePath + " "
   5250                             + parser.getPositionDescription());
   5251                     XmlUtils.skipCurrentTag(parser);
   5252                     continue;
   5253                 } else {
   5254                     outError[0] = "Bad element under <service>: " + parser.getName();
   5255                     return null;
   5256                 }
   5257             }
   5258         }
   5259 
   5260         if (!setExported) {
   5261             s.info.exported = s.intents.size() > 0;
   5262         }
   5263 
   5264         return s;
   5265     }
   5266 
   5267     private boolean isImplicitlyExposedIntent(IntentInfo intent) {
   5268         return intent.hasCategory(Intent.CATEGORY_BROWSABLE)
   5269                 || intent.hasAction(Intent.ACTION_SEND)
   5270                 || intent.hasAction(Intent.ACTION_SENDTO)
   5271                 || intent.hasAction(Intent.ACTION_SEND_MULTIPLE);
   5272     }
   5273 
   5274     private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag,
   5275             Component<?> outInfo, String[] outError) throws XmlPullParserException, IOException {
   5276         int outerDepth = parser.getDepth();
   5277         int type;
   5278         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   5279                && (type != XmlPullParser.END_TAG
   5280                        || parser.getDepth() > outerDepth)) {
   5281             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   5282                 continue;
   5283             }
   5284 
   5285             if (parser.getName().equals("meta-data")) {
   5286                 if ((outInfo.metaData=parseMetaData(res, parser,
   5287                         outInfo.metaData, outError)) == null) {
   5288                     return false;
   5289                 }
   5290             } else {
   5291                 if (!RIGID_PARSER) {
   5292                     Slog.w(TAG, "Unknown element under " + tag + ": "
   5293                             + parser.getName() + " at " + mArchiveSourcePath + " "
   5294                             + parser.getPositionDescription());
   5295                     XmlUtils.skipCurrentTag(parser);
   5296                     continue;
   5297                 } else {
   5298                     outError[0] = "Bad element under " + tag + ": " + parser.getName();
   5299                     return false;
   5300                 }
   5301             }
   5302         }
   5303         return true;
   5304     }
   5305 
   5306     private Bundle parseMetaData(Resources res,
   5307             XmlResourceParser parser, Bundle data, String[] outError)
   5308             throws XmlPullParserException, IOException {
   5309 
   5310         TypedArray sa = res.obtainAttributes(parser,
   5311                 com.android.internal.R.styleable.AndroidManifestMetaData);
   5312 
   5313         if (data == null) {
   5314             data = new Bundle();
   5315         }
   5316 
   5317         String name = sa.getNonConfigurationString(
   5318                 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
   5319         if (name == null) {
   5320             outError[0] = "<meta-data> requires an android:name attribute";
   5321             sa.recycle();
   5322             return null;
   5323         }
   5324 
   5325         name = name.intern();
   5326 
   5327         TypedValue v = sa.peekValue(
   5328                 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
   5329         if (v != null && v.resourceId != 0) {
   5330             //Slog.i(TAG, "Meta data ref " + name + ": " + v);
   5331             data.putInt(name, v.resourceId);
   5332         } else {
   5333             v = sa.peekValue(
   5334                     com.android.internal.R.styleable.AndroidManifestMetaData_value);
   5335             //Slog.i(TAG, "Meta data " + name + ": " + v);
   5336             if (v != null) {
   5337                 if (v.type == TypedValue.TYPE_STRING) {
   5338                     CharSequence cs = v.coerceToString();
   5339                     data.putString(name, cs != null ? cs.toString() : null);
   5340                 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
   5341                     data.putBoolean(name, v.data != 0);
   5342                 } else if (v.type >= TypedValue.TYPE_FIRST_INT
   5343                         && v.type <= TypedValue.TYPE_LAST_INT) {
   5344                     data.putInt(name, v.data);
   5345                 } else if (v.type == TypedValue.TYPE_FLOAT) {
   5346                     data.putFloat(name, v.getFloat());
   5347                 } else {
   5348                     if (!RIGID_PARSER) {
   5349                         Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
   5350                                 + parser.getName() + " at " + mArchiveSourcePath + " "
   5351                                 + parser.getPositionDescription());
   5352                     } else {
   5353                         outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
   5354                         data = null;
   5355                     }
   5356                 }
   5357             } else {
   5358                 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
   5359                 data = null;
   5360             }
   5361         }
   5362 
   5363         sa.recycle();
   5364 
   5365         XmlUtils.skipCurrentTag(parser);
   5366 
   5367         return data;
   5368     }
   5369 
   5370     private static VerifierInfo parseVerifier(AttributeSet attrs) {
   5371         String packageName = null;
   5372         String encodedPublicKey = null;
   5373 
   5374         final int attrCount = attrs.getAttributeCount();
   5375         for (int i = 0; i < attrCount; i++) {
   5376             final int attrResId = attrs.getAttributeNameResource(i);
   5377             switch (attrResId) {
   5378                 case com.android.internal.R.attr.name:
   5379                     packageName = attrs.getAttributeValue(i);
   5380                     break;
   5381 
   5382                 case com.android.internal.R.attr.publicKey:
   5383                     encodedPublicKey = attrs.getAttributeValue(i);
   5384                     break;
   5385             }
   5386         }
   5387 
   5388         if (packageName == null || packageName.length() == 0) {
   5389             Slog.i(TAG, "verifier package name was null; skipping");
   5390             return null;
   5391         }
   5392 
   5393         final PublicKey publicKey = parsePublicKey(encodedPublicKey);
   5394         if (publicKey == null) {
   5395             Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
   5396             return null;
   5397         }
   5398 
   5399         return new VerifierInfo(packageName, publicKey);
   5400     }
   5401 
   5402     public static final PublicKey parsePublicKey(final String encodedPublicKey) {
   5403         if (encodedPublicKey == null) {
   5404             Slog.w(TAG, "Could not parse null public key");
   5405             return null;
   5406         }
   5407 
   5408         EncodedKeySpec keySpec;
   5409         try {
   5410             final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
   5411             keySpec = new X509EncodedKeySpec(encoded);
   5412         } catch (IllegalArgumentException e) {
   5413             Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
   5414             return null;
   5415         }
   5416 
   5417         /* First try the key as an RSA key. */
   5418         try {
   5419             final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
   5420             return keyFactory.generatePublic(keySpec);
   5421         } catch (NoSuchAlgorithmException e) {
   5422             Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build");
   5423         } catch (InvalidKeySpecException e) {
   5424             // Not a RSA public key.
   5425         }
   5426 
   5427         /* Now try it as a ECDSA key. */
   5428         try {
   5429             final KeyFactory keyFactory = KeyFactory.getInstance("EC");
   5430             return keyFactory.generatePublic(keySpec);
   5431         } catch (NoSuchAlgorithmException e) {
   5432             Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build");
   5433         } catch (InvalidKeySpecException e) {
   5434             // Not a ECDSA public key.
   5435         }
   5436 
   5437         /* Now try it as a DSA key. */
   5438         try {
   5439             final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
   5440             return keyFactory.generatePublic(keySpec);
   5441         } catch (NoSuchAlgorithmException e) {
   5442             Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build");
   5443         } catch (InvalidKeySpecException e) {
   5444             // Not a DSA public key.
   5445         }
   5446 
   5447         /* Not a supported key type */
   5448         return null;
   5449     }
   5450 
   5451     private static final String ANDROID_RESOURCES
   5452             = "http://schemas.android.com/apk/res/android";
   5453 
   5454     private boolean parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs,
   5455             boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
   5456                     throws XmlPullParserException, IOException {
   5457 
   5458         TypedArray sa = res.obtainAttributes(parser,
   5459                 com.android.internal.R.styleable.AndroidManifestIntentFilter);
   5460 
   5461         int priority = sa.getInt(
   5462                 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
   5463         outInfo.setPriority(priority);
   5464 
   5465         int order = sa.getInt(
   5466                 com.android.internal.R.styleable.AndroidManifestIntentFilter_order, 0);
   5467         outInfo.setOrder(order);
   5468 
   5469         TypedValue v = sa.peekValue(
   5470                 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
   5471         if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
   5472             outInfo.nonLocalizedLabel = v.coerceToString();
   5473         }
   5474 
   5475         final boolean useRoundIcon =
   5476                 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
   5477         int roundIconVal = useRoundIcon ? sa.getResourceId(
   5478                 com.android.internal.R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0;
   5479         if (roundIconVal != 0) {
   5480             outInfo.icon = roundIconVal;
   5481         } else {
   5482             outInfo.icon = sa.getResourceId(
   5483                     com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
   5484         }
   5485 
   5486         outInfo.logo = sa.getResourceId(
   5487                 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
   5488 
   5489         outInfo.banner = sa.getResourceId(
   5490                 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
   5491 
   5492         if (allowAutoVerify) {
   5493             outInfo.setAutoVerify(sa.getBoolean(
   5494                     com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
   5495                     false));
   5496         }
   5497 
   5498         sa.recycle();
   5499 
   5500         int outerDepth = parser.getDepth();
   5501         int type;
   5502         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
   5503                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
   5504             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   5505                 continue;
   5506             }
   5507 
   5508             String nodeName = parser.getName();
   5509             if (nodeName.equals("action")) {
   5510                 String value = parser.getAttributeValue(
   5511                         ANDROID_RESOURCES, "name");
   5512                 if (value == null || value == "") {
   5513                     outError[0] = "No value supplied for <android:name>";
   5514                     return false;
   5515                 }
   5516                 XmlUtils.skipCurrentTag(parser);
   5517 
   5518                 outInfo.addAction(value);
   5519             } else if (nodeName.equals("category")) {
   5520                 String value = parser.getAttributeValue(
   5521                         ANDROID_RESOURCES, "name");
   5522                 if (value == null || value == "") {
   5523                     outError[0] = "No value supplied for <android:name>";
   5524                     return false;
   5525                 }
   5526                 XmlUtils.skipCurrentTag(parser);
   5527 
   5528                 outInfo.addCategory(value);
   5529 
   5530             } else if (nodeName.equals("data")) {
   5531                 sa = res.obtainAttributes(parser,
   5532                         com.android.internal.R.styleable.AndroidManifestData);
   5533 
   5534                 String str = sa.getNonConfigurationString(
   5535                         com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
   5536                 if (str != null) {
   5537                     try {
   5538                         outInfo.addDataType(str);
   5539                     } catch (IntentFilter.MalformedMimeTypeException e) {
   5540                         outError[0] = e.toString();
   5541                         sa.recycle();
   5542                         return false;
   5543                     }
   5544                 }
   5545 
   5546                 str = sa.getNonConfigurationString(
   5547                         com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
   5548                 if (str != null) {
   5549                     outInfo.addDataScheme(str);
   5550                 }
   5551 
   5552                 str = sa.getNonConfigurationString(
   5553                         com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
   5554                 if (str != null) {
   5555                     outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
   5556                 }
   5557 
   5558                 str = sa.getNonConfigurationString(
   5559                         com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
   5560                 if (str != null) {
   5561                     outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
   5562                 }
   5563 
   5564                 str = sa.getNonConfigurationString(
   5565                         com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
   5566                 if (str != null) {
   5567                     if (!allowGlobs) {
   5568                         outError[0] = "sspPattern not allowed here; ssp must be literal";
   5569                         return false;
   5570                     }
   5571                     outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
   5572                 }
   5573 
   5574                 String host = sa.getNonConfigurationString(
   5575                         com.android.internal.R.styleable.AndroidManifestData_host, 0);
   5576                 String port = sa.getNonConfigurationString(
   5577                         com.android.internal.R.styleable.AndroidManifestData_port, 0);
   5578                 if (host != null) {
   5579                     outInfo.addDataAuthority(host, port);
   5580                 }
   5581 
   5582                 str = sa.getNonConfigurationString(
   5583                         com.android.internal.R.styleable.AndroidManifestData_path, 0);
   5584                 if (str != null) {
   5585                     outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
   5586                 }
   5587 
   5588                 str = sa.getNonConfigurationString(
   5589                         com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
   5590                 if (str != null) {
   5591                     outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
   5592                 }
   5593 
   5594                 str = sa.getNonConfigurationString(
   5595                         com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
   5596                 if (str != null) {
   5597                     if (!allowGlobs) {
   5598                         outError[0] = "pathPattern not allowed here; path must be literal";
   5599                         return false;
   5600                     }
   5601                     outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
   5602                 }
   5603 
   5604                 str = sa.getNonConfigurationString(
   5605                         com.android.internal.R.styleable.AndroidManifestData_pathAdvancedPattern, 0);
   5606                 if (str != null) {
   5607                     if (!allowGlobs) {
   5608                         outError[0] = "pathAdvancedPattern not allowed here; path must be literal";
   5609                         return false;
   5610                     }
   5611                     outInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB);
   5612                 }
   5613 
   5614                 sa.recycle();
   5615                 XmlUtils.skipCurrentTag(parser);
   5616             } else if (!RIGID_PARSER) {
   5617                 Slog.w(TAG, "Unknown element under <intent-filter>: "
   5618                         + parser.getName() + " at " + mArchiveSourcePath + " "
   5619                         + parser.getPositionDescription());
   5620                 XmlUtils.skipCurrentTag(parser);
   5621             } else {
   5622                 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
   5623                 return false;
   5624             }
   5625         }
   5626 
   5627         outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
   5628 
   5629         if (DEBUG_PARSER) {
   5630             final StringBuilder cats = new StringBuilder("Intent d=");
   5631             cats.append(outInfo.hasDefault);
   5632             cats.append(", cat=");
   5633 
   5634             final Iterator<String> it = outInfo.categoriesIterator();
   5635             if (it != null) {
   5636                 while (it.hasNext()) {
   5637                     cats.append(' ');
   5638                     cats.append(it.next());
   5639                 }
   5640             }
   5641             Slog.d(TAG, cats.toString());
   5642         }
   5643 
   5644         return true;
   5645     }
   5646 
   5647     /**
   5648      *  A container for signing-related data of an application package.
   5649      * @hide
   5650      */
   5651     public static final class SigningDetails implements Parcelable {
   5652 
   5653         @IntDef({SigningDetails.SignatureSchemeVersion.UNKNOWN,
   5654                 SigningDetails.SignatureSchemeVersion.JAR,
   5655                 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2,
   5656                 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3})
   5657         public @interface SignatureSchemeVersion {
   5658             int UNKNOWN = 0;
   5659             int JAR = 1;
   5660             int SIGNING_BLOCK_V2 = 2;
   5661             int SIGNING_BLOCK_V3 = 3;
   5662         }
   5663 
   5664         @Nullable
   5665         public final Signature[] signatures;
   5666         @SignatureSchemeVersion
   5667         public final int signatureSchemeVersion;
   5668         @Nullable
   5669         public final ArraySet<PublicKey> publicKeys;
   5670 
   5671         /**
   5672          * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that
   5673          * contains two pieces of information:
   5674          *   1) the past signing certificates
   5675          *   2) the flags that APK wants to assign to each of the past signing certificates.
   5676          *
   5677          * This collection of {@code Signature} objects, each of which is formed from a former
   5678          * signing certificate of this APK before it was changed by signing certificate rotation,
   5679          * represents the first piece of information.  It is the APK saying to the rest of the
   5680          * world: "hey if you trust the old cert, you can trust me!"  This is useful, if for
   5681          * instance, the platform would like to determine whether or not to allow this APK to do
   5682          * something it would've allowed it to do under the old cert (like upgrade).
   5683          */
   5684         @Nullable
   5685         public final Signature[] pastSigningCertificates;
   5686 
   5687         /** special value used to see if cert is in package - not exposed to callers */
   5688         private static final int PAST_CERT_EXISTS = 0;
   5689 
   5690         @IntDef(
   5691                 flag = true,
   5692                 value = {CertCapabilities.INSTALLED_DATA,
   5693                         CertCapabilities.SHARED_USER_ID,
   5694                         CertCapabilities.PERMISSION,
   5695                         CertCapabilities.ROLLBACK})
   5696         public @interface CertCapabilities {
   5697 
   5698             /** accept data from already installed pkg with this cert */
   5699             int INSTALLED_DATA = 1;
   5700 
   5701             /** accept sharedUserId with pkg with this cert */
   5702             int SHARED_USER_ID = 2;
   5703 
   5704             /** grant SIGNATURE permissions to pkgs with this cert */
   5705             int PERMISSION = 4;
   5706 
   5707             /** allow pkg to update to one signed by this certificate */
   5708             int ROLLBACK = 8;
   5709 
   5710             /** allow pkg to continue to have auth access gated by this cert */
   5711             int AUTH = 16;
   5712         }
   5713 
   5714         /**
   5715          * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that
   5716          * contains two pieces of information:
   5717          *   1) the past signing certificates
   5718          *   2) the flags that APK wants to assign to each of the past signing certificates.
   5719          *
   5720          * These flags, which have a one-to-one relationship for the {@code pastSigningCertificates}
   5721          * collection, represent the second piece of information and are viewed as capabilities.
   5722          * They are an APK's way of telling the platform: "this is how I want to trust my old certs,
   5723          * please enforce that." This is useful for situation where this app itself is using its
   5724          * signing certificate as an authorization mechanism, like whether or not to allow another
   5725          * app to have its SIGNATURE permission.  An app could specify whether to allow other apps
   5726          * signed by its old cert 'X' to still get a signature permission it defines, for example.
   5727          */
   5728         @Nullable
   5729         public final int[] pastSigningCertificatesFlags;
   5730 
   5731         /** A representation of unknown signing details. Use instead of null. */
   5732         public static final SigningDetails UNKNOWN =
   5733                 new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null, null, null);
   5734 
   5735         @VisibleForTesting
   5736         public SigningDetails(Signature[] signatures,
   5737                 @SignatureSchemeVersion int signatureSchemeVersion,
   5738                 ArraySet<PublicKey> keys, Signature[] pastSigningCertificates,
   5739                 int[] pastSigningCertificatesFlags) {
   5740             this.signatures = signatures;
   5741             this.signatureSchemeVersion = signatureSchemeVersion;
   5742             this.publicKeys = keys;
   5743             this.pastSigningCertificates = pastSigningCertificates;
   5744             this.pastSigningCertificatesFlags = pastSigningCertificatesFlags;
   5745         }
   5746 
   5747         public SigningDetails(Signature[] signatures,
   5748                 @SignatureSchemeVersion int signatureSchemeVersion,
   5749                 Signature[] pastSigningCertificates, int[] pastSigningCertificatesFlags)
   5750                 throws CertificateException {
   5751             this(signatures, signatureSchemeVersion, toSigningKeys(signatures),
   5752                     pastSigningCertificates, pastSigningCertificatesFlags);
   5753         }
   5754 
   5755         public SigningDetails(Signature[] signatures,
   5756                 @SignatureSchemeVersion int signatureSchemeVersion)
   5757                 throws CertificateException {
   5758             this(signatures, signatureSchemeVersion,
   5759                     null, null);
   5760         }
   5761 
   5762         public SigningDetails(SigningDetails orig) {
   5763             if (orig != null) {
   5764                 if (orig.signatures != null) {
   5765                     this.signatures = orig.signatures.clone();
   5766                 } else {
   5767                     this.signatures = null;
   5768                 }
   5769                 this.signatureSchemeVersion = orig.signatureSchemeVersion;
   5770                 this.publicKeys = new ArraySet<>(orig.publicKeys);
   5771                 if (orig.pastSigningCertificates != null) {
   5772                     this.pastSigningCertificates = orig.pastSigningCertificates.clone();
   5773                     this.pastSigningCertificatesFlags = orig.pastSigningCertificatesFlags.clone();
   5774                 } else {
   5775                     this.pastSigningCertificates = null;
   5776                     this.pastSigningCertificatesFlags = null;
   5777                 }
   5778             } else {
   5779                 this.signatures = null;
   5780                 this.signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
   5781                 this.publicKeys = null;
   5782                 this.pastSigningCertificates = null;
   5783                 this.pastSigningCertificatesFlags = null;
   5784             }
   5785         }
   5786 
   5787         /** Returns true if the signing details have one or more signatures. */
   5788         public boolean hasSignatures() {
   5789             return signatures != null && signatures.length > 0;
   5790         }
   5791 
   5792         /** Returns true if the signing details have past signing certificates. */
   5793         public boolean hasPastSigningCertificates() {
   5794             return pastSigningCertificates != null && pastSigningCertificates.length > 0;
   5795         }
   5796 
   5797         /**
   5798          * Determines if the provided {@code oldDetails} is an ancestor of or the same as this one.
   5799          * If the {@code oldDetails} signing certificate appears in our pastSigningCertificates,
   5800          * then that means it has authorized a signing certificate rotation, which eventually leads
   5801          * to our certificate, and thus can be trusted. If this method evaluates to true, this
   5802          * SigningDetails object should be trusted if the previous one is.
   5803          */
   5804         public boolean hasAncestorOrSelf(SigningDetails oldDetails) {
   5805             if (this == UNKNOWN || oldDetails == UNKNOWN) {
   5806                 return false;
   5807             }
   5808             if (oldDetails.signatures.length > 1) {
   5809 
   5810                 // multiple-signer packages cannot rotate signing certs, so we just compare current
   5811                 // signers for an exact match
   5812                 return signaturesMatchExactly(oldDetails);
   5813             } else {
   5814 
   5815                 // we may have signing certificate rotation history, check to see if the oldDetails
   5816                 // was one of our old signing certificates
   5817                 return hasCertificate(oldDetails.signatures[0]);
   5818             }
   5819         }
   5820 
   5821         /**
   5822          * Similar to {@code hasAncestorOrSelf}.  Returns true only if this {@code SigningDetails}
   5823          * is a descendant of {@code oldDetails}, not if they're the same.  This is used to
   5824          * determine if this object is newer than the provided one.
   5825          */
   5826         public boolean hasAncestor(SigningDetails oldDetails) {
   5827             if (this == UNKNOWN || oldDetails == UNKNOWN) {
   5828                 return false;
   5829             }
   5830             if (this.hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
   5831 
   5832                 // the last entry in pastSigningCertificates is the current signer, ignore it
   5833                 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
   5834                     if (pastSigningCertificates[i].equals(oldDetails.signatures[i])) {
   5835                         return true;
   5836                     }
   5837                 }
   5838             }
   5839             return false;
   5840         }
   5841 
   5842         /**
   5843          * Determines if the provided {@code oldDetails} is an ancestor of this one, and whether or
   5844          * not this one grants it the provided capability, represented by the {@code flags}
   5845          * parameter.  In the event of signing certificate rotation, a package may still interact
   5846          * with entities signed by its old signing certificate and not want to break previously
   5847          * functioning behavior.  The {@code flags} value determines which capabilities the app
   5848          * signed by the newer signing certificate would like to continue to give to its previous
   5849          * signing certificate(s).
   5850          */
   5851         public boolean checkCapability(SigningDetails oldDetails, @CertCapabilities int flags) {
   5852             if (this == UNKNOWN || oldDetails == UNKNOWN) {
   5853                 return false;
   5854             }
   5855             if (oldDetails.signatures.length > 1) {
   5856 
   5857                 // multiple-signer packages cannot rotate signing certs, so we must have an exact
   5858                 // match, which also means all capabilities are granted
   5859                 return signaturesMatchExactly(oldDetails);
   5860             } else {
   5861 
   5862                 // we may have signing certificate rotation history, check to see if the oldDetails
   5863                 // was one of our old signing certificates, and if we grant it the capability it's
   5864                 // requesting
   5865                 return hasCertificate(oldDetails.signatures[0], flags);
   5866             }
   5867         }
   5868 
   5869         /**
   5870          * A special case of {@code checkCapability} which re-encodes both sets of signing
   5871          * certificates to counteract a previous re-encoding.
   5872          */
   5873         public boolean checkCapabilityRecover(SigningDetails oldDetails,
   5874                 @CertCapabilities int flags) throws CertificateException {
   5875             if (oldDetails == UNKNOWN || this == UNKNOWN) {
   5876                 return false;
   5877             }
   5878             if (hasPastSigningCertificates() && oldDetails.signatures.length == 1) {
   5879 
   5880                 // signing certificates may have rotated, check entire history for effective match
   5881                 for (int i = 0; i < pastSigningCertificates.length; i++) {
   5882                     if (Signature.areEffectiveMatch(
   5883                             oldDetails.signatures[0],
   5884                             pastSigningCertificates[i])
   5885                             && pastSigningCertificatesFlags[i] == flags) {
   5886                         return true;
   5887                     }
   5888                 }
   5889             } else {
   5890                 return Signature.areEffectiveMatch(oldDetails.signatures, signatures);
   5891             }
   5892             return false;
   5893         }
   5894 
   5895         /**
   5896          * Determine if {@code signature} is in this SigningDetails' signing certificate history,
   5897          * including the current signer.  Automatically returns false if this object has multiple
   5898          * signing certificates, since rotation is only supported for single-signers; this is
   5899          * enforced by {@code hasCertificateInternal}.
   5900          */
   5901         public boolean hasCertificate(Signature signature) {
   5902             return hasCertificateInternal(signature, PAST_CERT_EXISTS);
   5903         }
   5904 
   5905         /**
   5906          * Determine if {@code signature} is in this SigningDetails' signing certificate history,
   5907          * including the current signer, and whether or not it has the given permission.
   5908          * Certificates which match our current signer automatically get all capabilities.
   5909          * Automatically returns false if this object has multiple signing certificates, since
   5910          * rotation is only supported for single-signers.
   5911          */
   5912         public boolean hasCertificate(Signature signature, @CertCapabilities int flags) {
   5913             return hasCertificateInternal(signature, flags);
   5914         }
   5915 
   5916         /** Convenient wrapper for calling {@code hasCertificate} with certificate's raw bytes. */
   5917         public boolean hasCertificate(byte[] certificate) {
   5918             Signature signature = new Signature(certificate);
   5919             return hasCertificate(signature);
   5920         }
   5921 
   5922         private boolean hasCertificateInternal(Signature signature, int flags) {
   5923             if (this == UNKNOWN) {
   5924                 return false;
   5925             }
   5926 
   5927             // only single-signed apps can have pastSigningCertificates
   5928             if (hasPastSigningCertificates()) {
   5929 
   5930                 // check all past certs, except for the current one, which automatically gets all
   5931                 // capabilities, since it is the same as the current signature
   5932                 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
   5933                     if (pastSigningCertificates[i].equals(signature)) {
   5934                         if (flags == PAST_CERT_EXISTS
   5935                                 || (flags & pastSigningCertificatesFlags[i]) == flags) {
   5936                             return true;
   5937                         }
   5938                     }
   5939                 }
   5940             }
   5941 
   5942             // not in previous certs signing history, just check the current signer and make sure
   5943             // we are singly-signed
   5944             return signatures.length == 1 && signatures[0].equals(signature);
   5945         }
   5946 
   5947         /**
   5948          * Determines if the provided {@code sha256String} is an ancestor of this one, and whether
   5949          * or not this one grants it the provided capability, represented by the {@code flags}
   5950          * parameter.  In the event of signing certificate rotation, a package may still interact
   5951          * with entities signed by its old signing certificate and not want to break previously
   5952          * functioning behavior.  The {@code flags} value determines which capabilities the app
   5953          * signed by the newer signing certificate would like to continue to give to its previous
   5954          * signing certificate(s).
   5955          *
   5956          * @param sha256String A hex-encoded representation of a sha256 digest.  In the case of an
   5957          *                     app with multiple signers, this represents the hex-encoded sha256
   5958          *                     digest of the combined hex-encoded sha256 digests of each individual
   5959          *                     signing certificate according to {@link
   5960          *                     PackageUtils#computeSignaturesSha256Digest(Signature[])}
   5961          */
   5962         public boolean checkCapability(String sha256String, @CertCapabilities int flags) {
   5963             if (this == UNKNOWN) {
   5964                 return false;
   5965             }
   5966 
   5967             // first see if the hash represents a single-signer in our signing history
   5968             byte[] sha256Bytes = ByteStringUtils.fromHexToByteArray(sha256String);
   5969             if (hasSha256Certificate(sha256Bytes, flags)) {
   5970                 return true;
   5971             }
   5972 
   5973             // Not in signing history, either represents multiple signatures or not a match.
   5974             // Multiple signers can't rotate, so no need to check flags, just see if the SHAs match.
   5975             // We already check the single-signer case above as part of hasSha256Certificate, so no
   5976             // need to verify we have multiple signers, just run the old check
   5977             // just consider current signing certs
   5978             final String[] mSignaturesSha256Digests =
   5979                     PackageUtils.computeSignaturesSha256Digests(signatures);
   5980             final String mSignaturesSha256Digest =
   5981                     PackageUtils.computeSignaturesSha256Digest(mSignaturesSha256Digests);
   5982             return mSignaturesSha256Digest.equals(sha256String);
   5983         }
   5984 
   5985         /**
   5986          * Determine if the {@code sha256Certificate} is in this SigningDetails' signing certificate
   5987          * history, including the current signer.  Automatically returns false if this object has
   5988          * multiple signing certificates, since rotation is only supported for single-signers.
   5989          */
   5990         public boolean hasSha256Certificate(byte[] sha256Certificate) {
   5991             return hasSha256CertificateInternal(sha256Certificate, PAST_CERT_EXISTS);
   5992         }
   5993 
   5994         /**
   5995          * Determine if the {@code sha256Certificate} certificate hash corresponds to a signing
   5996          * certificate in this SigningDetails' signing certificate history, including the current
   5997          * signer, and whether or not it has the given permission.  Certificates which match our
   5998          * current signer automatically get all capabilities. Automatically returns false if this
   5999          * object has multiple signing certificates, since rotation is only supported for
   6000          * single-signers.
   6001          */
   6002         public boolean hasSha256Certificate(byte[] sha256Certificate, @CertCapabilities int flags) {
   6003             return hasSha256CertificateInternal(sha256Certificate, flags);
   6004         }
   6005 
   6006         private boolean hasSha256CertificateInternal(byte[] sha256Certificate, int flags) {
   6007             if (this == UNKNOWN) {
   6008                 return false;
   6009             }
   6010             if (hasPastSigningCertificates()) {
   6011 
   6012                 // check all past certs, except for the last one, which automatically gets all
   6013                 // capabilities, since it is the same as the current signature, and is checked below
   6014                 for (int i = 0; i < pastSigningCertificates.length - 1; i++) {
   6015                     byte[] digest = PackageUtils.computeSha256DigestBytes(
   6016                             pastSigningCertificates[i].toByteArray());
   6017                     if (Arrays.equals(sha256Certificate, digest)) {
   6018                         if (flags == PAST_CERT_EXISTS
   6019                                 || (flags & pastSigningCertificatesFlags[i]) == flags) {
   6020                             return true;
   6021                         }
   6022                     }
   6023                 }
   6024             }
   6025 
   6026             // not in previous certs signing history, just check the current signer
   6027             if (signatures.length == 1) {
   6028                 byte[] digest =
   6029                         PackageUtils.computeSha256DigestBytes(signatures[0].toByteArray());
   6030                 return Arrays.equals(sha256Certificate, digest);
   6031             }
   6032             return false;
   6033         }
   6034 
   6035         /** Returns true if the signatures in this and other match exactly. */
   6036         public boolean signaturesMatchExactly(SigningDetails other) {
   6037             return Signature.areExactMatch(this.signatures, other.signatures);
   6038         }
   6039 
   6040         @Override
   6041         public int describeContents() {
   6042             return 0;
   6043         }
   6044 
   6045         @Override
   6046         public void writeToParcel(Parcel dest, int flags) {
   6047             boolean isUnknown = UNKNOWN == this;
   6048             dest.writeBoolean(isUnknown);
   6049             if (isUnknown) {
   6050                 return;
   6051             }
   6052             dest.writeTypedArray(this.signatures, flags);
   6053             dest.writeInt(this.signatureSchemeVersion);
   6054             dest.writeArraySet(this.publicKeys);
   6055             dest.writeTypedArray(this.pastSigningCertificates, flags);
   6056             dest.writeIntArray(this.pastSigningCertificatesFlags);
   6057         }
   6058 
   6059         protected SigningDetails(Parcel in) {
   6060             final ClassLoader boot = Object.class.getClassLoader();
   6061             this.signatures = in.createTypedArray(Signature.CREATOR);
   6062             this.signatureSchemeVersion = in.readInt();
   6063             this.publicKeys = (ArraySet<PublicKey>) in.readArraySet(boot);
   6064             this.pastSigningCertificates = in.createTypedArray(Signature.CREATOR);
   6065             this.pastSigningCertificatesFlags = in.createIntArray();
   6066         }
   6067 
   6068         public static final Creator<SigningDetails> CREATOR = new Creator<SigningDetails>() {
   6069             @Override
   6070             public SigningDetails createFromParcel(Parcel source) {
   6071                 if (source.readBoolean()) {
   6072                     return UNKNOWN;
   6073                 }
   6074                 return new SigningDetails(source);
   6075             }
   6076 
   6077             @Override
   6078             public SigningDetails[] newArray(int size) {
   6079                 return new SigningDetails[size];
   6080             }
   6081         };
   6082 
   6083         @Override
   6084         public boolean equals(Object o) {
   6085             if (this == o) return true;
   6086             if (!(o instanceof SigningDetails)) return false;
   6087 
   6088             SigningDetails that = (SigningDetails) o;
   6089 
   6090             if (signatureSchemeVersion != that.signatureSchemeVersion) return false;
   6091             if (!Signature.areExactMatch(signatures, that.signatures)) return false;
   6092             if (publicKeys != null) {
   6093                 if (!publicKeys.equals((that.publicKeys))) {
   6094                     return false;
   6095                 }
   6096             } else if (that.publicKeys != null) {
   6097                 return false;
   6098             }
   6099 
   6100             // can't use Signature.areExactMatch() because order matters with the past signing certs
   6101             if (!Arrays.equals(pastSigningCertificates, that.pastSigningCertificates)) {
   6102                 return false;
   6103             }
   6104             if (!Arrays.equals(pastSigningCertificatesFlags, that.pastSigningCertificatesFlags)) {
   6105                 return false;
   6106             }
   6107 
   6108             return true;
   6109         }
   6110 
   6111         @Override
   6112         public int hashCode() {
   6113             int result = +Arrays.hashCode(signatures);
   6114             result = 31 * result + signatureSchemeVersion;
   6115             result = 31 * result + (publicKeys != null ? publicKeys.hashCode() : 0);
   6116             result = 31 * result + Arrays.hashCode(pastSigningCertificates);
   6117             result = 31 * result + Arrays.hashCode(pastSigningCertificatesFlags);
   6118             return result;
   6119         }
   6120 
   6121         /**
   6122          * Builder of {@code SigningDetails} instances.
   6123          */
   6124         public static class Builder {
   6125             private Signature[] mSignatures;
   6126             private int mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
   6127             private Signature[] mPastSigningCertificates;
   6128             private int[] mPastSigningCertificatesFlags;
   6129 
   6130             public Builder() {
   6131             }
   6132 
   6133             /** get signing certificates used to sign the current APK */
   6134             public Builder setSignatures(Signature[] signatures) {
   6135                 mSignatures = signatures;
   6136                 return this;
   6137             }
   6138 
   6139             /** set the signature scheme version used to sign the APK */
   6140             public Builder setSignatureSchemeVersion(int signatureSchemeVersion) {
   6141                 mSignatureSchemeVersion = signatureSchemeVersion;
   6142                 return this;
   6143             }
   6144 
   6145             /** set the signing certificates by which the APK proved it can be authenticated */
   6146             public Builder setPastSigningCertificates(Signature[] pastSigningCertificates) {
   6147                 mPastSigningCertificates = pastSigningCertificates;
   6148                 return this;
   6149             }
   6150 
   6151             /** set the flags for the {@code pastSigningCertificates} */
   6152             public Builder setPastSigningCertificatesFlags(int[] pastSigningCertificatesFlags) {
   6153                 mPastSigningCertificatesFlags = pastSigningCertificatesFlags;
   6154                 return this;
   6155             }
   6156 
   6157             private void checkInvariants() {
   6158                 // must have signatures and scheme version set
   6159                 if (mSignatures == null) {
   6160                     throw new IllegalStateException("SigningDetails requires the current signing"
   6161                             + " certificates.");
   6162                 }
   6163 
   6164                 // pastSigningCerts and flags must match up
   6165                 boolean pastMismatch = false;
   6166                 if (mPastSigningCertificates != null && mPastSigningCertificatesFlags != null) {
   6167                     if (mPastSigningCertificates.length != mPastSigningCertificatesFlags.length) {
   6168                         pastMismatch = true;
   6169                     }
   6170                 } else if (!(mPastSigningCertificates == null
   6171                         && mPastSigningCertificatesFlags == null)) {
   6172                     pastMismatch = true;
   6173                 }
   6174                 if (pastMismatch) {
   6175                     throw new IllegalStateException("SigningDetails must have a one to one mapping "
   6176                             + "between pastSigningCertificates and pastSigningCertificatesFlags");
   6177                 }
   6178             }
   6179             /** build a {@code SigningDetails} object */
   6180             public SigningDetails build()
   6181                     throws CertificateException {
   6182                 checkInvariants();
   6183                 return new SigningDetails(mSignatures, mSignatureSchemeVersion,
   6184                         mPastSigningCertificates, mPastSigningCertificatesFlags);
   6185             }
   6186         }
   6187     }
   6188 
   6189     /**
   6190      * Representation of a full package parsed from APK files on disk. A package
   6191      * consists of a single base APK, and zero or more split APKs.
   6192      */
   6193     public final static class Package implements Parcelable {
   6194 
   6195         public String packageName;
   6196 
   6197         // The package name declared in the manifest as the package can be
   6198         // renamed, for example static shared libs use synthetic package names.
   6199         public String manifestPackageName;
   6200 
   6201         /** Names of any split APKs, ordered by parsed splitName */
   6202         public String[] splitNames;
   6203 
   6204         // TODO: work towards making these paths invariant
   6205 
   6206         public String volumeUuid;
   6207 
   6208         /**
   6209          * Path where this package was found on disk. For monolithic packages
   6210          * this is path to single base APK file; for cluster packages this is
   6211          * path to the cluster directory.
   6212          */
   6213         public String codePath;
   6214 
   6215         /** Path of base APK */
   6216         public String baseCodePath;
   6217         /** Paths of any split APKs, ordered by parsed splitName */
   6218         public String[] splitCodePaths;
   6219 
   6220         /** Revision code of base APK */
   6221         public int baseRevisionCode;
   6222         /** Revision codes of any split APKs, ordered by parsed splitName */
   6223         public int[] splitRevisionCodes;
   6224 
   6225         /** Flags of any split APKs; ordered by parsed splitName */
   6226         public int[] splitFlags;
   6227 
   6228         /**
   6229          * Private flags of any split APKs; ordered by parsed splitName.
   6230          *
   6231          * {@hide}
   6232          */
   6233         public int[] splitPrivateFlags;
   6234 
   6235         public boolean baseHardwareAccelerated;
   6236 
   6237         // For now we only support one application per package.
   6238         public ApplicationInfo applicationInfo = new ApplicationInfo();
   6239 
   6240         public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
   6241         public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
   6242         public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
   6243         public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
   6244         public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
   6245         public final ArrayList<Service> services = new ArrayList<Service>(0);
   6246         public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
   6247 
   6248         public final ArrayList<String> requestedPermissions = new ArrayList<String>();
   6249 
   6250         public ArrayList<String> protectedBroadcasts;
   6251 
   6252         public Package parentPackage;
   6253         public ArrayList<Package> childPackages;
   6254 
   6255         public String staticSharedLibName = null;
   6256         public long staticSharedLibVersion = 0;
   6257         public ArrayList<String> libraryNames = null;
   6258         public ArrayList<String> usesLibraries = null;
   6259         public ArrayList<String> usesStaticLibraries = null;
   6260         public long[] usesStaticLibrariesVersions = null;
   6261         public String[][] usesStaticLibrariesCertDigests = null;
   6262         public ArrayList<String> usesOptionalLibraries = null;
   6263         public String[] usesLibraryFiles = null;
   6264 
   6265         public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
   6266 
   6267         public ArrayList<String> mOriginalPackages = null;
   6268         public String mRealPackage = null;
   6269         public ArrayList<String> mAdoptPermissions = null;
   6270 
   6271         // We store the application meta-data independently to avoid multiple unwanted references
   6272         public Bundle mAppMetaData = null;
   6273 
   6274         // The version code declared for this package.
   6275         public int mVersionCode;
   6276 
   6277         // The major version code declared for this package.
   6278         public int mVersionCodeMajor;
   6279 
   6280         // Return long containing mVersionCode and mVersionCodeMajor.
   6281         public long getLongVersionCode() {
   6282             return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
   6283         }
   6284 
   6285         // The version name declared for this package.
   6286         public String mVersionName;
   6287 
   6288         // The shared user id that this package wants to use.
   6289         public String mSharedUserId;
   6290 
   6291         // The shared user label that this package wants to use.
   6292         public int mSharedUserLabel;
   6293 
   6294         // Signatures that were read from the package.
   6295         @NonNull public SigningDetails mSigningDetails = SigningDetails.UNKNOWN;
   6296 
   6297         // For use by package manager service for quick lookup of
   6298         // preferred up order.
   6299         public int mPreferredOrder = 0;
   6300 
   6301         // For use by package manager to keep track of when a package was last used.
   6302         public long[] mLastPackageUsageTimeInMills =
   6303                 new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
   6304 
   6305         // // User set enabled state.
   6306         // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
   6307         //
   6308         // // Whether the package has been stopped.
   6309         // public boolean mSetStopped = false;
   6310 
   6311         // Additional data supplied by callers.
   6312         public Object mExtras;
   6313 
   6314         // Applications hardware preferences
   6315         public ArrayList<ConfigurationInfo> configPreferences = null;
   6316 
   6317         // Applications requested features
   6318         public ArrayList<FeatureInfo> reqFeatures = null;
   6319 
   6320         // Applications requested feature groups
   6321         public ArrayList<FeatureGroupInfo> featureGroups = null;
   6322 
   6323         public int installLocation;
   6324 
   6325         public boolean coreApp;
   6326 
   6327         /* An app that's required for all users and cannot be uninstalled for a user */
   6328         public boolean mRequiredForAllUsers;
   6329 
   6330         /* The restricted account authenticator type that is used by this application */
   6331         public String mRestrictedAccountType;
   6332 
   6333         /* The required account type without which this application will not function */
   6334         public String mRequiredAccountType;
   6335 
   6336         public String mOverlayTarget;
   6337         public String mOverlayCategory;
   6338         public int mOverlayPriority;
   6339         public boolean mOverlayIsStatic;
   6340 
   6341         public int mCompileSdkVersion;
   6342         public String mCompileSdkVersionCodename;
   6343 
   6344         /**
   6345          * Data used to feed the KeySetManagerService
   6346          */
   6347         public ArraySet<String> mUpgradeKeySets;
   6348         public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
   6349 
   6350         /**
   6351          * The install time abi override for this package, if any.
   6352          *
   6353          * TODO: This seems like a horrible place to put the abiOverride because
   6354          * this isn't something the packageParser parsers. However, this fits in with
   6355          * the rest of the PackageManager where package scanning randomly pushes
   6356          * and prods fields out of {@code this.applicationInfo}.
   6357          */
   6358         public String cpuAbiOverride;
   6359         /**
   6360          * The install time abi override to choose 32bit abi's when multiple abi's
   6361          * are present. This is only meaningfull for multiarch applications.
   6362          * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
   6363          */
   6364         public boolean use32bitAbi;
   6365 
   6366         public byte[] restrictUpdateHash;
   6367 
   6368         /** Set if the app or any of its components are visible to instant applications. */
   6369         public boolean visibleToInstantApps;
   6370         /** Whether or not the package is a stub and must be replaced by the full version. */
   6371         public boolean isStub;
   6372 
   6373         public Package(String packageName) {
   6374             this.packageName = packageName;
   6375             this.manifestPackageName = packageName;
   6376             applicationInfo.packageName = packageName;
   6377             applicationInfo.uid = -1;
   6378         }
   6379 
   6380         public void setApplicationVolumeUuid(String volumeUuid) {
   6381             final UUID storageUuid = StorageManager.convert(volumeUuid);
   6382             this.applicationInfo.volumeUuid = volumeUuid;
   6383             this.applicationInfo.storageUuid = storageUuid;
   6384             if (childPackages != null) {
   6385                 final int packageCount = childPackages.size();
   6386                 for (int i = 0; i < packageCount; i++) {
   6387                     childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
   6388                     childPackages.get(i).applicationInfo.storageUuid = storageUuid;
   6389                 }
   6390             }
   6391         }
   6392 
   6393         public void setApplicationInfoCodePath(String codePath) {
   6394             this.applicationInfo.setCodePath(codePath);
   6395             if (childPackages != null) {
   6396                 final int packageCount = childPackages.size();
   6397                 for (int i = 0; i < packageCount; i++) {
   6398                     childPackages.get(i).applicationInfo.setCodePath(codePath);
   6399                 }
   6400             }
   6401         }
   6402 
   6403         /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
   6404         @Deprecated
   6405         public void setApplicationInfoResourcePath(String resourcePath) {
   6406             this.applicationInfo.setResourcePath(resourcePath);
   6407             if (childPackages != null) {
   6408                 final int packageCount = childPackages.size();
   6409                 for (int i = 0; i < packageCount; i++) {
   6410                     childPackages.get(i).applicationInfo.setResourcePath(resourcePath);
   6411                 }
   6412             }
   6413         }
   6414 
   6415         /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
   6416         @Deprecated
   6417         public void setApplicationInfoBaseResourcePath(String resourcePath) {
   6418             this.applicationInfo.setBaseResourcePath(resourcePath);
   6419             if (childPackages != null) {
   6420                 final int packageCount = childPackages.size();
   6421                 for (int i = 0; i < packageCount; i++) {
   6422                     childPackages.get(i).applicationInfo.setBaseResourcePath(resourcePath);
   6423                 }
   6424             }
   6425         }
   6426 
   6427         public void setApplicationInfoBaseCodePath(String baseCodePath) {
   6428             this.applicationInfo.setBaseCodePath(baseCodePath);
   6429             if (childPackages != null) {
   6430                 final int packageCount = childPackages.size();
   6431                 for (int i = 0; i < packageCount; i++) {
   6432                     childPackages.get(i).applicationInfo.setBaseCodePath(baseCodePath);
   6433                 }
   6434             }
   6435         }
   6436 
   6437         public List<String> getChildPackageNames() {
   6438             if (childPackages == null) {
   6439                 return null;
   6440             }
   6441             final int childCount = childPackages.size();
   6442             final List<String> childPackageNames = new ArrayList<>(childCount);
   6443             for (int i = 0; i < childCount; i++) {
   6444                 String childPackageName = childPackages.get(i).packageName;
   6445                 childPackageNames.add(childPackageName);
   6446             }
   6447             return childPackageNames;
   6448         }
   6449 
   6450         public boolean hasChildPackage(String packageName) {
   6451             final int childCount = (childPackages != null) ? childPackages.size() : 0;
   6452             for (int i = 0; i < childCount; i++) {
   6453                 if (childPackages.get(i).packageName.equals(packageName)) {
   6454                     return true;
   6455                 }
   6456             }
   6457             return false;
   6458         }
   6459 
   6460         public void setApplicationInfoSplitCodePaths(String[] splitCodePaths) {
   6461             this.applicationInfo.setSplitCodePaths(splitCodePaths);
   6462             // Children have no splits
   6463         }
   6464 
   6465         /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
   6466         @Deprecated
   6467         public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) {
   6468             this.applicationInfo.setSplitResourcePaths(resroucePaths);
   6469             // Children have no splits
   6470         }
   6471 
   6472         public void setSplitCodePaths(String[] codePaths) {
   6473             this.splitCodePaths = codePaths;
   6474         }
   6475 
   6476         public void setCodePath(String codePath) {
   6477             this.codePath = codePath;
   6478             if (childPackages != null) {
   6479                 final int packageCount = childPackages.size();
   6480                 for (int i = 0; i < packageCount; i++) {
   6481                     childPackages.get(i).codePath = codePath;
   6482                 }
   6483             }
   6484         }
   6485 
   6486         public void setBaseCodePath(String baseCodePath) {
   6487             this.baseCodePath = baseCodePath;
   6488             if (childPackages != null) {
   6489                 final int packageCount = childPackages.size();
   6490                 for (int i = 0; i < packageCount; i++) {
   6491                     childPackages.get(i).baseCodePath = baseCodePath;
   6492                 }
   6493             }
   6494         }
   6495 
   6496         /** Sets signing details on the package and any of its children. */
   6497         public void setSigningDetails(@NonNull SigningDetails signingDetails) {
   6498             mSigningDetails = signingDetails;
   6499             if (childPackages != null) {
   6500                 final int packageCount = childPackages.size();
   6501                 for (int i = 0; i < packageCount; i++) {
   6502                     childPackages.get(i).mSigningDetails = signingDetails;
   6503                 }
   6504             }
   6505         }
   6506 
   6507         public void setVolumeUuid(String volumeUuid) {
   6508             this.volumeUuid = volumeUuid;
   6509             if (childPackages != null) {
   6510                 final int packageCount = childPackages.size();
   6511                 for (int i = 0; i < packageCount; i++) {
   6512                     childPackages.get(i).volumeUuid = volumeUuid;
   6513                 }
   6514             }
   6515         }
   6516 
   6517         public void setApplicationInfoFlags(int mask, int flags) {
   6518             applicationInfo.flags = (applicationInfo.flags & ~mask) | (mask & flags);
   6519             if (childPackages != null) {
   6520                 final int packageCount = childPackages.size();
   6521                 for (int i = 0; i < packageCount; i++) {
   6522                     childPackages.get(i).applicationInfo.flags =
   6523                             (applicationInfo.flags & ~mask) | (mask & flags);
   6524                 }
   6525             }
   6526         }
   6527 
   6528         public void setUse32bitAbi(boolean use32bitAbi) {
   6529             this.use32bitAbi = use32bitAbi;
   6530             if (childPackages != null) {
   6531                 final int packageCount = childPackages.size();
   6532                 for (int i = 0; i < packageCount; i++) {
   6533                     childPackages.get(i).use32bitAbi = use32bitAbi;
   6534                 }
   6535             }
   6536         }
   6537 
   6538         public boolean isLibrary() {
   6539             return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames);
   6540         }
   6541 
   6542         public List<String> getAllCodePaths() {
   6543             ArrayList<String> paths = new ArrayList<>();
   6544             paths.add(baseCodePath);
   6545             if (!ArrayUtils.isEmpty(splitCodePaths)) {
   6546                 Collections.addAll(paths, splitCodePaths);
   6547             }
   6548             return paths;
   6549         }
   6550 
   6551         /**
   6552          * Filtered set of {@link #getAllCodePaths()} that excludes
   6553          * resource-only APKs.
   6554          */
   6555         public List<String> getAllCodePathsExcludingResourceOnly() {
   6556             ArrayList<String> paths = new ArrayList<>();
   6557             if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
   6558                 paths.add(baseCodePath);
   6559             }
   6560             if (!ArrayUtils.isEmpty(splitCodePaths)) {
   6561                 for (int i = 0; i < splitCodePaths.length; i++) {
   6562                     if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
   6563                         paths.add(splitCodePaths[i]);
   6564                     }
   6565                 }
   6566             }
   6567             return paths;
   6568         }
   6569 
   6570         public void setPackageName(String newName) {
   6571             packageName = newName;
   6572             applicationInfo.packageName = newName;
   6573             for (int i=permissions.size()-1; i>=0; i--) {
   6574                 permissions.get(i).setPackageName(newName);
   6575             }
   6576             for (int i=permissionGroups.size()-1; i>=0; i--) {
   6577                 permissionGroups.get(i).setPackageName(newName);
   6578             }
   6579             for (int i=activities.size()-1; i>=0; i--) {
   6580                 activities.get(i).setPackageName(newName);
   6581             }
   6582             for (int i=receivers.size()-1; i>=0; i--) {
   6583                 receivers.get(i).setPackageName(newName);
   6584             }
   6585             for (int i=providers.size()-1; i>=0; i--) {
   6586                 providers.get(i).setPackageName(newName);
   6587             }
   6588             for (int i=services.size()-1; i>=0; i--) {
   6589                 services.get(i).setPackageName(newName);
   6590             }
   6591             for (int i=instrumentation.size()-1; i>=0; i--) {
   6592                 instrumentation.get(i).setPackageName(newName);
   6593             }
   6594         }
   6595 
   6596         public boolean hasComponentClassName(String name) {
   6597             for (int i=activities.size()-1; i>=0; i--) {
   6598                 if (name.equals(activities.get(i).className)) {
   6599                     return true;
   6600                 }
   6601             }
   6602             for (int i=receivers.size()-1; i>=0; i--) {
   6603                 if (name.equals(receivers.get(i).className)) {
   6604                     return true;
   6605                 }
   6606             }
   6607             for (int i=providers.size()-1; i>=0; i--) {
   6608                 if (name.equals(providers.get(i).className)) {
   6609                     return true;
   6610                 }
   6611             }
   6612             for (int i=services.size()-1; i>=0; i--) {
   6613                 if (name.equals(services.get(i).className)) {
   6614                     return true;
   6615                 }
   6616             }
   6617             for (int i=instrumentation.size()-1; i>=0; i--) {
   6618                 if (name.equals(instrumentation.get(i).className)) {
   6619                     return true;
   6620                 }
   6621             }
   6622             return false;
   6623         }
   6624 
   6625         /** @hide */
   6626         public boolean isExternal() {
   6627             return applicationInfo.isExternal();
   6628         }
   6629 
   6630         /** @hide */
   6631         public boolean isForwardLocked() {
   6632             return applicationInfo.isForwardLocked();
   6633         }
   6634 
   6635         /** @hide */
   6636         public boolean isOem() {
   6637             return applicationInfo.isOem();
   6638         }
   6639 
   6640         /** @hide */
   6641         public boolean isVendor() {
   6642             return applicationInfo.isVendor();
   6643         }
   6644 
   6645         /** @hide */
   6646         public boolean isProduct() {
   6647             return applicationInfo.isProduct();
   6648         }
   6649 
   6650         /** @hide */
   6651         public boolean isPrivileged() {
   6652             return applicationInfo.isPrivilegedApp();
   6653         }
   6654 
   6655         /** @hide */
   6656         public boolean isSystem() {
   6657             return applicationInfo.isSystemApp();
   6658         }
   6659 
   6660         /** @hide */
   6661         public boolean isUpdatedSystemApp() {
   6662             return applicationInfo.isUpdatedSystemApp();
   6663         }
   6664 
   6665         /** @hide */
   6666         public boolean canHaveOatDir() {
   6667             // The following app types CANNOT have oat directory
   6668             // - non-updated system apps
   6669             // - forward-locked apps or apps installed in ASEC containers
   6670             return (!isSystem() || isUpdatedSystemApp())
   6671                     && !isForwardLocked() && !applicationInfo.isExternalAsec();
   6672         }
   6673 
   6674         public boolean isMatch(int flags) {
   6675             if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
   6676                 return isSystem();
   6677             }
   6678             return true;
   6679         }
   6680 
   6681         public long getLatestPackageUseTimeInMills() {
   6682             long latestUse = 0L;
   6683             for (long use : mLastPackageUsageTimeInMills) {
   6684                 latestUse = Math.max(latestUse, use);
   6685             }
   6686             return latestUse;
   6687         }
   6688 
   6689         public long getLatestForegroundPackageUseTimeInMills() {
   6690             int[] foregroundReasons = {
   6691                 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
   6692                 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
   6693             };
   6694 
   6695             long latestUse = 0L;
   6696             for (int reason : foregroundReasons) {
   6697                 latestUse = Math.max(latestUse, mLastPackageUsageTimeInMills[reason]);
   6698             }
   6699             return latestUse;
   6700         }
   6701 
   6702         public String toString() {
   6703             return "Package{"
   6704                 + Integer.toHexString(System.identityHashCode(this))
   6705                 + " " + packageName + "}";
   6706         }
   6707 
   6708         @Override
   6709         public int describeContents() {
   6710             return 0;
   6711         }
   6712 
   6713         public Package(Parcel dest) {
   6714             // We use the boot classloader for all classes that we load.
   6715             final ClassLoader boot = Object.class.getClassLoader();
   6716 
   6717             packageName = dest.readString().intern();
   6718             manifestPackageName = dest.readString();
   6719             splitNames = dest.readStringArray();
   6720             volumeUuid = dest.readString();
   6721             codePath = dest.readString();
   6722             baseCodePath = dest.readString();
   6723             splitCodePaths = dest.readStringArray();
   6724             baseRevisionCode = dest.readInt();
   6725             splitRevisionCodes = dest.createIntArray();
   6726             splitFlags = dest.createIntArray();
   6727             splitPrivateFlags = dest.createIntArray();
   6728             baseHardwareAccelerated = (dest.readInt() == 1);
   6729             applicationInfo = dest.readParcelable(boot);
   6730             if (applicationInfo.permission != null) {
   6731                 applicationInfo.permission = applicationInfo.permission.intern();
   6732             }
   6733 
   6734             // We don't serialize the "owner" package and the application info object for each of
   6735             // these components, in order to save space and to avoid circular dependencies while
   6736             // serialization. We need to fix them all up here.
   6737             dest.readParcelableList(permissions, boot);
   6738             fixupOwner(permissions);
   6739             dest.readParcelableList(permissionGroups, boot);
   6740             fixupOwner(permissionGroups);
   6741             dest.readParcelableList(activities, boot);
   6742             fixupOwner(activities);
   6743             dest.readParcelableList(receivers, boot);
   6744             fixupOwner(receivers);
   6745             dest.readParcelableList(providers, boot);
   6746             fixupOwner(providers);
   6747             dest.readParcelableList(services, boot);
   6748             fixupOwner(services);
   6749             dest.readParcelableList(instrumentation, boot);
   6750             fixupOwner(instrumentation);
   6751 
   6752             dest.readStringList(requestedPermissions);
   6753             internStringArrayList(requestedPermissions);
   6754             protectedBroadcasts = dest.createStringArrayList();
   6755             internStringArrayList(protectedBroadcasts);
   6756 
   6757             parentPackage = dest.readParcelable(boot);
   6758 
   6759             childPackages = new ArrayList<>();
   6760             dest.readParcelableList(childPackages, boot);
   6761             if (childPackages.size() == 0) {
   6762                 childPackages = null;
   6763             }
   6764 
   6765             staticSharedLibName = dest.readString();
   6766             if (staticSharedLibName != null) {
   6767                 staticSharedLibName = staticSharedLibName.intern();
   6768             }
   6769             staticSharedLibVersion = dest.readLong();
   6770             libraryNames = dest.createStringArrayList();
   6771             internStringArrayList(libraryNames);
   6772             usesLibraries = dest.createStringArrayList();
   6773             internStringArrayList(usesLibraries);
   6774             usesOptionalLibraries = dest.createStringArrayList();
   6775             internStringArrayList(usesOptionalLibraries);
   6776             usesLibraryFiles = dest.readStringArray();
   6777 
   6778             final int libCount = dest.readInt();
   6779             if (libCount > 0) {
   6780                 usesStaticLibraries = new ArrayList<>(libCount);
   6781                 dest.readStringList(usesStaticLibraries);
   6782                 internStringArrayList(usesStaticLibraries);
   6783                 usesStaticLibrariesVersions = new long[libCount];
   6784                 dest.readLongArray(usesStaticLibrariesVersions);
   6785                 usesStaticLibrariesCertDigests = new String[libCount][];
   6786                 for (int i = 0; i < libCount; i++) {
   6787                     usesStaticLibrariesCertDigests[i] = dest.createStringArray();
   6788                 }
   6789             }
   6790 
   6791             preferredActivityFilters = new ArrayList<>();
   6792             dest.readParcelableList(preferredActivityFilters, boot);
   6793             if (preferredActivityFilters.size() == 0) {
   6794                 preferredActivityFilters = null;
   6795             }
   6796 
   6797             mOriginalPackages = dest.createStringArrayList();
   6798             mRealPackage = dest.readString();
   6799             mAdoptPermissions = dest.createStringArrayList();
   6800             mAppMetaData = dest.readBundle();
   6801             mVersionCode = dest.readInt();
   6802             mVersionCodeMajor = dest.readInt();
   6803             mVersionName = dest.readString();
   6804             if (mVersionName != null) {
   6805                 mVersionName = mVersionName.intern();
   6806             }
   6807             mSharedUserId = dest.readString();
   6808             if (mSharedUserId != null) {
   6809                 mSharedUserId = mSharedUserId.intern();
   6810             }
   6811             mSharedUserLabel = dest.readInt();
   6812 
   6813             mSigningDetails = dest.readParcelable(boot);
   6814 
   6815             mPreferredOrder = dest.readInt();
   6816 
   6817             // long[] packageUsageTimeMillis is not persisted because it isn't information that
   6818             // is parsed from the APK.
   6819 
   6820             // Object mExtras is not persisted because it is not information that is read from
   6821             // the APK, rather, it is supplied by callers.
   6822 
   6823 
   6824             configPreferences = new ArrayList<>();
   6825             dest.readParcelableList(configPreferences, boot);
   6826             if (configPreferences.size() == 0) {
   6827                 configPreferences = null;
   6828             }
   6829 
   6830             reqFeatures = new ArrayList<>();
   6831             dest.readParcelableList(reqFeatures, boot);
   6832             if (reqFeatures.size() == 0) {
   6833                 reqFeatures = null;
   6834             }
   6835 
   6836             featureGroups = new ArrayList<>();
   6837             dest.readParcelableList(featureGroups, boot);
   6838             if (featureGroups.size() == 0) {
   6839                 featureGroups = null;
   6840             }
   6841 
   6842             installLocation = dest.readInt();
   6843             coreApp = (dest.readInt() == 1);
   6844             mRequiredForAllUsers = (dest.readInt() == 1);
   6845             mRestrictedAccountType = dest.readString();
   6846             mRequiredAccountType = dest.readString();
   6847             mOverlayTarget = dest.readString();
   6848             mOverlayCategory = dest.readString();
   6849             mOverlayPriority = dest.readInt();
   6850             mOverlayIsStatic = (dest.readInt() == 1);
   6851             mCompileSdkVersion = dest.readInt();
   6852             mCompileSdkVersionCodename = dest.readString();
   6853             mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
   6854 
   6855             mKeySetMapping = readKeySetMapping(dest);
   6856 
   6857             cpuAbiOverride = dest.readString();
   6858             use32bitAbi = (dest.readInt() == 1);
   6859             restrictUpdateHash = dest.createByteArray();
   6860             visibleToInstantApps = dest.readInt() == 1;
   6861         }
   6862 
   6863         private static void internStringArrayList(List<String> list) {
   6864             if (list != null) {
   6865                 final int N = list.size();
   6866                 for (int i = 0; i < N; ++i) {
   6867                     list.set(i, list.get(i).intern());
   6868                 }
   6869             }
   6870         }
   6871 
   6872         /**
   6873          * Sets the package owner and the the {@code applicationInfo} for every component
   6874          * owner by this package.
   6875          */
   6876         private void fixupOwner(List<? extends Component<?>> list) {
   6877             if (list != null) {
   6878                 for (Component<?> c : list) {
   6879                     c.owner = this;
   6880                     if (c instanceof Activity) {
   6881                         ((Activity) c).info.applicationInfo = this.applicationInfo;
   6882                     } else if (c instanceof Service) {
   6883                         ((Service) c).info.applicationInfo = this.applicationInfo;
   6884                     } else if (c instanceof Provider) {
   6885                         ((Provider) c).info.applicationInfo = this.applicationInfo;
   6886                     }
   6887                 }
   6888             }
   6889         }
   6890 
   6891         @Override
   6892         public void writeToParcel(Parcel dest, int flags) {
   6893             dest.writeString(packageName);
   6894             dest.writeString(manifestPackageName);
   6895             dest.writeStringArray(splitNames);
   6896             dest.writeString(volumeUuid);
   6897             dest.writeString(codePath);
   6898             dest.writeString(baseCodePath);
   6899             dest.writeStringArray(splitCodePaths);
   6900             dest.writeInt(baseRevisionCode);
   6901             dest.writeIntArray(splitRevisionCodes);
   6902             dest.writeIntArray(splitFlags);
   6903             dest.writeIntArray(splitPrivateFlags);
   6904             dest.writeInt(baseHardwareAccelerated ? 1 : 0);
   6905             dest.writeParcelable(applicationInfo, flags);
   6906 
   6907             dest.writeParcelableList(permissions, flags);
   6908             dest.writeParcelableList(permissionGroups, flags);
   6909             dest.writeParcelableList(activities, flags);
   6910             dest.writeParcelableList(receivers, flags);
   6911             dest.writeParcelableList(providers, flags);
   6912             dest.writeParcelableList(services, flags);
   6913             dest.writeParcelableList(instrumentation, flags);
   6914 
   6915             dest.writeStringList(requestedPermissions);
   6916             dest.writeStringList(protectedBroadcasts);
   6917 
   6918             // TODO: This doesn't work: b/64295061
   6919             dest.writeParcelable(parentPackage, flags);
   6920             dest.writeParcelableList(childPackages, flags);
   6921 
   6922             dest.writeString(staticSharedLibName);
   6923             dest.writeLong(staticSharedLibVersion);
   6924             dest.writeStringList(libraryNames);
   6925             dest.writeStringList(usesLibraries);
   6926             dest.writeStringList(usesOptionalLibraries);
   6927             dest.writeStringArray(usesLibraryFiles);
   6928 
   6929             if (ArrayUtils.isEmpty(usesStaticLibraries)) {
   6930                 dest.writeInt(-1);
   6931             } else {
   6932                 dest.writeInt(usesStaticLibraries.size());
   6933                 dest.writeStringList(usesStaticLibraries);
   6934                 dest.writeLongArray(usesStaticLibrariesVersions);
   6935                 for (String[] usesStaticLibrariesCertDigest : usesStaticLibrariesCertDigests) {
   6936                     dest.writeStringArray(usesStaticLibrariesCertDigest);
   6937                 }
   6938             }
   6939 
   6940             dest.writeParcelableList(preferredActivityFilters, flags);
   6941 
   6942             dest.writeStringList(mOriginalPackages);
   6943             dest.writeString(mRealPackage);
   6944             dest.writeStringList(mAdoptPermissions);
   6945             dest.writeBundle(mAppMetaData);
   6946             dest.writeInt(mVersionCode);
   6947             dest.writeInt(mVersionCodeMajor);
   6948             dest.writeString(mVersionName);
   6949             dest.writeString(mSharedUserId);
   6950             dest.writeInt(mSharedUserLabel);
   6951 
   6952             dest.writeParcelable(mSigningDetails, flags);
   6953 
   6954             dest.writeInt(mPreferredOrder);
   6955 
   6956             // long[] packageUsageTimeMillis is not persisted because it isn't information that
   6957             // is parsed from the APK.
   6958 
   6959             // Object mExtras is not persisted because it is not information that is read from
   6960             // the APK, rather, it is supplied by callers.
   6961 
   6962             dest.writeParcelableList(configPreferences, flags);
   6963             dest.writeParcelableList(reqFeatures, flags);
   6964             dest.writeParcelableList(featureGroups, flags);
   6965 
   6966             dest.writeInt(installLocation);
   6967             dest.writeInt(coreApp ? 1 : 0);
   6968             dest.writeInt(mRequiredForAllUsers ? 1 : 0);
   6969             dest.writeString(mRestrictedAccountType);
   6970             dest.writeString(mRequiredAccountType);
   6971             dest.writeString(mOverlayTarget);
   6972             dest.writeString(mOverlayCategory);
   6973             dest.writeInt(mOverlayPriority);
   6974             dest.writeInt(mOverlayIsStatic ? 1 : 0);
   6975             dest.writeInt(mCompileSdkVersion);
   6976             dest.writeString(mCompileSdkVersionCodename);
   6977             dest.writeArraySet(mUpgradeKeySets);
   6978             writeKeySetMapping(dest, mKeySetMapping);
   6979             dest.writeString(cpuAbiOverride);
   6980             dest.writeInt(use32bitAbi ? 1 : 0);
   6981             dest.writeByteArray(restrictUpdateHash);
   6982             dest.writeInt(visibleToInstantApps ? 1 : 0);
   6983         }
   6984 
   6985 
   6986         /**
   6987          * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
   6988          */
   6989         private static void writeKeySetMapping(
   6990                 Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
   6991             if (keySetMapping == null) {
   6992                 dest.writeInt(-1);
   6993                 return;
   6994             }
   6995 
   6996             final int N = keySetMapping.size();
   6997             dest.writeInt(N);
   6998 
   6999             for (int i = 0; i < N; i++) {
   7000                 dest.writeString(keySetMapping.keyAt(i));
   7001                 ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
   7002                 if (keys == null) {
   7003                     dest.writeInt(-1);
   7004                     continue;
   7005                 }
   7006 
   7007                 final int M = keys.size();
   7008                 dest.writeInt(M);
   7009                 for (int j = 0; j < M; j++) {
   7010                     dest.writeSerializable(keys.valueAt(j));
   7011                 }
   7012             }
   7013         }
   7014 
   7015         /**
   7016          * Reads a keyset mapping from the given parcel at the given data position. May return
   7017          * {@code null} if the serialized mapping was {@code null}.
   7018          */
   7019         private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
   7020             final int N = in.readInt();
   7021             if (N == -1) {
   7022                 return null;
   7023             }
   7024 
   7025             ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
   7026             for (int i = 0; i < N; ++i) {
   7027                 String key = in.readString();
   7028                 final int M = in.readInt();
   7029                 if (M == -1) {
   7030                     keySetMapping.put(key, null);
   7031                     continue;
   7032                 }
   7033 
   7034                 ArraySet<PublicKey> keys = new ArraySet<>(M);
   7035                 for (int j = 0; j < M; ++j) {
   7036                     PublicKey pk = (PublicKey) in.readSerializable();
   7037                     keys.add(pk);
   7038                 }
   7039 
   7040                 keySetMapping.put(key, keys);
   7041             }
   7042 
   7043             return keySetMapping;
   7044         }
   7045 
   7046         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
   7047             public Package createFromParcel(Parcel in) {
   7048                 return new Package(in);
   7049             }
   7050 
   7051             public Package[] newArray(int size) {
   7052                 return new Package[size];
   7053             }
   7054         };
   7055     }
   7056 
   7057     public static abstract class Component<II extends IntentInfo> {
   7058         public final ArrayList<II> intents;
   7059         public final String className;
   7060 
   7061         public Bundle metaData;
   7062         public Package owner;
   7063         /** The order of this component in relation to its peers */
   7064         public int order;
   7065 
   7066         ComponentName componentName;
   7067         String componentShortName;
   7068 
   7069         public Component(Package _owner) {
   7070             owner = _owner;
   7071             intents = null;
   7072             className = null;
   7073         }
   7074 
   7075         public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
   7076             owner = args.owner;
   7077             intents = new ArrayList<II>(0);
   7078             if (parsePackageItemInfo(args.owner, outInfo, args.outError, args.tag, args.sa,
   7079                     true /*nameRequired*/, args.nameRes, args.labelRes, args.iconRes,
   7080                     args.roundIconRes, args.logoRes, args.bannerRes)) {
   7081                 className = outInfo.name;
   7082             } else {
   7083                 className = null;
   7084             }
   7085         }
   7086 
   7087         public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
   7088             this(args, (PackageItemInfo)outInfo);
   7089             if (args.outError[0] != null) {
   7090                 return;
   7091             }
   7092 
   7093             if (args.processRes != 0) {
   7094                 CharSequence pname;
   7095                 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
   7096                     pname = args.sa.getNonConfigurationString(args.processRes,
   7097                             Configuration.NATIVE_CONFIG_VERSION);
   7098                 } else {
   7099                     // Some older apps have been seen to use a resource reference
   7100                     // here that on older builds was ignored (with a warning).  We
   7101                     // need to continue to do this for them so they don't break.
   7102                     pname = args.sa.getNonResourceString(args.processRes);
   7103                 }
   7104                 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
   7105                         owner.applicationInfo.processName, pname,
   7106                         args.flags, args.sepProcesses, args.outError);
   7107             }
   7108 
   7109             if (args.descriptionRes != 0) {
   7110                 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
   7111             }
   7112 
   7113             outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
   7114         }
   7115 
   7116         public Component(Component<II> clone) {
   7117             owner = clone.owner;
   7118             intents = clone.intents;
   7119             className = clone.className;
   7120             componentName = clone.componentName;
   7121             componentShortName = clone.componentShortName;
   7122         }
   7123 
   7124         public ComponentName getComponentName() {
   7125             if (componentName != null) {
   7126                 return componentName;
   7127             }
   7128             if (className != null) {
   7129                 componentName = new ComponentName(owner.applicationInfo.packageName,
   7130                         className);
   7131             }
   7132             return componentName;
   7133         }
   7134 
   7135         protected Component(Parcel in) {
   7136             className = in.readString();
   7137             metaData = in.readBundle();
   7138             intents = createIntentsList(in);
   7139 
   7140             owner = null;
   7141         }
   7142 
   7143         protected void writeToParcel(Parcel dest, int flags) {
   7144             dest.writeString(className);
   7145             dest.writeBundle(metaData);
   7146 
   7147             writeIntentsList(intents, dest, flags);
   7148         }
   7149 
   7150         /**
   7151          * <p>
   7152          * Implementation note: The serialized form for the intent list also contains the name
   7153          * of the concrete class that's stored in the list, and assumes that every element of the
   7154          * list is of the same type. This is very similar to the original parcelable mechanism.
   7155          * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable
   7156          * and is public API. It also declares Parcelable related methods as final which means
   7157          * we can't extend them. The approach of using composition instead of inheritance leads to
   7158          * a large set of cascading changes in the PackageManagerService, which seem undesirable.
   7159          *
   7160          * <p>
   7161          * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up
   7162          * to make sure their owner fields are consistent. See {@code fixupOwner}.
   7163          */
   7164         private static void writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out,
   7165                                              int flags) {
   7166             if (list == null) {
   7167                 out.writeInt(-1);
   7168                 return;
   7169             }
   7170 
   7171             final int N = list.size();
   7172             out.writeInt(N);
   7173 
   7174             // Don't bother writing the component name if the list is empty.
   7175             if (N > 0) {
   7176                 IntentInfo info = list.get(0);
   7177                 out.writeString(info.getClass().getName());
   7178 
   7179                 for (int i = 0; i < N;i++) {
   7180                     list.get(i).writeIntentInfoToParcel(out, flags);
   7181                 }
   7182             }
   7183         }
   7184 
   7185         private static <T extends IntentInfo> ArrayList<T> createIntentsList(Parcel in) {
   7186             int N = in.readInt();
   7187             if (N == -1) {
   7188                 return null;
   7189             }
   7190 
   7191             if (N == 0) {
   7192                 return new ArrayList<>(0);
   7193             }
   7194 
   7195             String componentName = in.readString();
   7196             final ArrayList<T> intentsList;
   7197             try {
   7198                 final Class<T> cls = (Class<T>) Class.forName(componentName);
   7199                 final Constructor<T> cons = cls.getConstructor(Parcel.class);
   7200 
   7201                 intentsList = new ArrayList<>(N);
   7202                 for (int i = 0; i < N; ++i) {
   7203                     intentsList.add(cons.newInstance(in));
   7204                 }
   7205             } catch (ReflectiveOperationException ree) {
   7206                 throw new AssertionError("Unable to construct intent list for: " + componentName);
   7207             }
   7208 
   7209             return intentsList;
   7210         }
   7211 
   7212         public void appendComponentShortName(StringBuilder sb) {
   7213             ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
   7214         }
   7215 
   7216         public void printComponentShortName(PrintWriter pw) {
   7217             ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
   7218         }
   7219 
   7220         public void setPackageName(String packageName) {
   7221             componentName = null;
   7222             componentShortName = null;
   7223         }
   7224     }
   7225 
   7226     public final static class Permission extends Component<IntentInfo> implements Parcelable {
   7227         public final PermissionInfo info;
   7228         public boolean tree;
   7229         public PermissionGroup group;
   7230 
   7231         public Permission(Package _owner) {
   7232             super(_owner);
   7233             info = new PermissionInfo();
   7234         }
   7235 
   7236         public Permission(Package _owner, PermissionInfo _info) {
   7237             super(_owner);
   7238             info = _info;
   7239         }
   7240 
   7241         public void setPackageName(String packageName) {
   7242             super.setPackageName(packageName);
   7243             info.packageName = packageName;
   7244         }
   7245 
   7246         public String toString() {
   7247             return "Permission{"
   7248                 + Integer.toHexString(System.identityHashCode(this))
   7249                 + " " + info.name + "}";
   7250         }
   7251 
   7252         @Override
   7253         public int describeContents() {
   7254             return 0;
   7255         }
   7256 
   7257         @Override
   7258         public void writeToParcel(Parcel dest, int flags) {
   7259             super.writeToParcel(dest, flags);
   7260             dest.writeParcelable(info, flags);
   7261             dest.writeInt(tree ? 1 : 0);
   7262             dest.writeParcelable(group, flags);
   7263         }
   7264 
   7265         /** @hide */
   7266         public boolean isAppOp() {
   7267             return info.isAppOp();
   7268         }
   7269 
   7270         private Permission(Parcel in) {
   7271             super(in);
   7272             final ClassLoader boot = Object.class.getClassLoader();
   7273             info = in.readParcelable(boot);
   7274             if (info.group != null) {
   7275                 info.group = info.group.intern();
   7276             }
   7277 
   7278             tree = (in.readInt() == 1);
   7279             group = in.readParcelable(boot);
   7280         }
   7281 
   7282         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Permission>() {
   7283             public Permission createFromParcel(Parcel in) {
   7284                 return new Permission(in);
   7285             }
   7286 
   7287             public Permission[] newArray(int size) {
   7288                 return new Permission[size];
   7289             }
   7290         };
   7291     }
   7292 
   7293     public final static class PermissionGroup extends Component<IntentInfo> implements Parcelable {
   7294         public final PermissionGroupInfo info;
   7295 
   7296         public PermissionGroup(Package _owner) {
   7297             super(_owner);
   7298             info = new PermissionGroupInfo();
   7299         }
   7300 
   7301         public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
   7302             super(_owner);
   7303             info = _info;
   7304         }
   7305 
   7306         public void setPackageName(String packageName) {
   7307             super.setPackageName(packageName);
   7308             info.packageName = packageName;
   7309         }
   7310 
   7311         public String toString() {
   7312             return "PermissionGroup{"
   7313                 + Integer.toHexString(System.identityHashCode(this))
   7314                 + " " + info.name + "}";
   7315         }
   7316 
   7317         @Override
   7318         public int describeContents() {
   7319             return 0;
   7320         }
   7321 
   7322         @Override
   7323         public void writeToParcel(Parcel dest, int flags) {
   7324             super.writeToParcel(dest, flags);
   7325             dest.writeParcelable(info, flags);
   7326         }
   7327 
   7328         private PermissionGroup(Parcel in) {
   7329             super(in);
   7330             info = in.readParcelable(Object.class.getClassLoader());
   7331         }
   7332 
   7333         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<PermissionGroup>() {
   7334             public PermissionGroup createFromParcel(Parcel in) {
   7335                 return new PermissionGroup(in);
   7336             }
   7337 
   7338             public PermissionGroup[] newArray(int size) {
   7339                 return new PermissionGroup[size];
   7340             }
   7341         };
   7342     }
   7343 
   7344     private static boolean copyNeeded(int flags, Package p,
   7345             PackageUserState state, Bundle metaData, int userId) {
   7346         if (userId != UserHandle.USER_SYSTEM) {
   7347             // We always need to copy for other users, since we need
   7348             // to fix up the uid.
   7349             return true;
   7350         }
   7351         if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
   7352             boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
   7353             if (p.applicationInfo.enabled != enabled) {
   7354                 return true;
   7355             }
   7356         }
   7357         boolean suspended = (p.applicationInfo.flags & FLAG_SUSPENDED) != 0;
   7358         if (state.suspended != suspended) {
   7359             return true;
   7360         }
   7361         if (!state.installed || state.hidden) {
   7362             return true;
   7363         }
   7364         if (state.stopped) {
   7365             return true;
   7366         }
   7367         if (state.instantApp != p.applicationInfo.isInstantApp()) {
   7368             return true;
   7369         }
   7370         if ((flags & PackageManager.GET_META_DATA) != 0
   7371                 && (metaData != null || p.mAppMetaData != null)) {
   7372             return true;
   7373         }
   7374         if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
   7375                 && p.usesLibraryFiles != null) {
   7376             return true;
   7377         }
   7378         if (p.staticSharedLibName != null) {
   7379             return true;
   7380         }
   7381         return false;
   7382     }
   7383 
   7384     public static ApplicationInfo generateApplicationInfo(Package p, int flags,
   7385             PackageUserState state) {
   7386         return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
   7387     }
   7388 
   7389     private static void updateApplicationInfo(ApplicationInfo ai, int flags,
   7390             PackageUserState state) {
   7391         // CompatibilityMode is global state.
   7392         if (!sCompatibilityModeEnabled) {
   7393             ai.disableCompatibilityMode();
   7394         }
   7395         if (state.installed) {
   7396             ai.flags |= ApplicationInfo.FLAG_INSTALLED;
   7397         } else {
   7398             ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
   7399         }
   7400         if (state.suspended) {
   7401             ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
   7402         } else {
   7403             ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
   7404         }
   7405         if (state.instantApp) {
   7406             ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT;
   7407         } else {
   7408             ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT;
   7409         }
   7410         if (state.virtualPreload) {
   7411             ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
   7412         } else {
   7413             ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
   7414         }
   7415         if (state.hidden) {
   7416             ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
   7417         } else {
   7418             ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
   7419         }
   7420         if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
   7421             ai.enabled = true;
   7422         } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
   7423             ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
   7424         } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
   7425                 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
   7426             ai.enabled = false;
   7427         }
   7428         ai.enabledSetting = state.enabled;
   7429         if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
   7430             ai.category = state.categoryHint;
   7431         }
   7432         if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
   7433             ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
   7434         }
   7435         ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
   7436         ai.resourceDirs = state.overlayPaths;
   7437     }
   7438 
   7439     public static ApplicationInfo generateApplicationInfo(Package p, int flags,
   7440             PackageUserState state, int userId) {
   7441         if (p == null) return null;
   7442         if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
   7443             return null;
   7444         }
   7445         if (!copyNeeded(flags, p, state, null, userId)
   7446                 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
   7447                         || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
   7448             // In this case it is safe to directly modify the internal ApplicationInfo state:
   7449             // - CompatibilityMode is global state, so will be the same for every call.
   7450             // - We only come in to here if the app should reported as installed; this is the
   7451             // default state, and we will do a copy otherwise.
   7452             // - The enable state will always be reported the same for the application across
   7453             // calls; the only exception is for the UNTIL_USED mode, and in that case we will
   7454             // be doing a copy.
   7455             updateApplicationInfo(p.applicationInfo, flags, state);
   7456             return p.applicationInfo;
   7457         }
   7458 
   7459         // Make shallow copy so we can store the metadata/libraries safely
   7460         ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
   7461         ai.initForUser(userId);
   7462         if ((flags & PackageManager.GET_META_DATA) != 0) {
   7463             ai.metaData = p.mAppMetaData;
   7464         }
   7465         if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
   7466             ai.sharedLibraryFiles = p.usesLibraryFiles;
   7467         }
   7468         if (state.stopped) {
   7469             ai.flags |= ApplicationInfo.FLAG_STOPPED;
   7470         } else {
   7471             ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
   7472         }
   7473         updateApplicationInfo(ai, flags, state);
   7474         return ai;
   7475     }
   7476 
   7477     public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
   7478             PackageUserState state, int userId) {
   7479         if (ai == null) return null;
   7480         if (!checkUseInstalledOrHidden(flags, state, ai)) {
   7481             return null;
   7482         }
   7483         // This is only used to return the ResolverActivity; we will just always
   7484         // make a copy.
   7485         ai = new ApplicationInfo(ai);
   7486         ai.initForUser(userId);
   7487         if (state.stopped) {
   7488             ai.flags |= ApplicationInfo.FLAG_STOPPED;
   7489         } else {
   7490             ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
   7491         }
   7492         updateApplicationInfo(ai, flags, state);
   7493         return ai;
   7494     }
   7495 
   7496     public static final PermissionInfo generatePermissionInfo(
   7497             Permission p, int flags) {
   7498         if (p == null) return null;
   7499         if ((flags&PackageManager.GET_META_DATA) == 0) {
   7500             return p.info;
   7501         }
   7502         PermissionInfo pi = new PermissionInfo(p.info);
   7503         pi.metaData = p.metaData;
   7504         return pi;
   7505     }
   7506 
   7507     public static final PermissionGroupInfo generatePermissionGroupInfo(
   7508             PermissionGroup pg, int flags) {
   7509         if (pg == null) return null;
   7510         if ((flags&PackageManager.GET_META_DATA) == 0) {
   7511             return pg.info;
   7512         }
   7513         PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
   7514         pgi.metaData = pg.metaData;
   7515         return pgi;
   7516     }
   7517 
   7518     public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable {
   7519         public final ActivityInfo info;
   7520         private boolean mHasMaxAspectRatio;
   7521 
   7522         private boolean hasMaxAspectRatio() {
   7523             return mHasMaxAspectRatio;
   7524         }
   7525 
   7526         public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
   7527             super(args, _info);
   7528             info = _info;
   7529             info.applicationInfo = args.owner.applicationInfo;
   7530         }
   7531 
   7532         public void setPackageName(String packageName) {
   7533             super.setPackageName(packageName);
   7534             info.packageName = packageName;
   7535         }
   7536 
   7537 
   7538         private void setMaxAspectRatio(float maxAspectRatio) {
   7539             if (info.resizeMode == RESIZE_MODE_RESIZEABLE
   7540                     || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
   7541                 // Resizeable activities can be put in any aspect ratio.
   7542                 return;
   7543             }
   7544 
   7545             if (maxAspectRatio < 1.0f && maxAspectRatio != 0) {
   7546                 // Ignore any value lesser than 1.0.
   7547                 return;
   7548             }
   7549 
   7550             info.maxAspectRatio = maxAspectRatio;
   7551             mHasMaxAspectRatio = true;
   7552         }
   7553 
   7554         public String toString() {
   7555             StringBuilder sb = new StringBuilder(128);
   7556             sb.append("Activity{");
   7557             sb.append(Integer.toHexString(System.identityHashCode(this)));
   7558             sb.append(' ');
   7559             appendComponentShortName(sb);
   7560             sb.append('}');
   7561             return sb.toString();
   7562         }
   7563 
   7564         @Override
   7565         public int describeContents() {
   7566             return 0;
   7567         }
   7568 
   7569         @Override
   7570         public void writeToParcel(Parcel dest, int flags) {
   7571             super.writeToParcel(dest, flags);
   7572             dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
   7573             dest.writeBoolean(mHasMaxAspectRatio);
   7574         }
   7575 
   7576         private Activity(Parcel in) {
   7577             super(in);
   7578             info = in.readParcelable(Object.class.getClassLoader());
   7579             mHasMaxAspectRatio = in.readBoolean();
   7580 
   7581             for (ActivityIntentInfo aii : intents) {
   7582                 aii.activity = this;
   7583                 order = Math.max(aii.getOrder(), order);
   7584             }
   7585 
   7586             if (info.permission != null) {
   7587                 info.permission = info.permission.intern();
   7588             }
   7589         }
   7590 
   7591         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Activity>() {
   7592             public Activity createFromParcel(Parcel in) {
   7593                 return new Activity(in);
   7594             }
   7595 
   7596             public Activity[] newArray(int size) {
   7597                 return new Activity[size];
   7598             }
   7599         };
   7600     }
   7601 
   7602     public static final ActivityInfo generateActivityInfo(Activity a, int flags,
   7603             PackageUserState state, int userId) {
   7604         if (a == null) return null;
   7605         if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
   7606             return null;
   7607         }
   7608         if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
   7609             updateApplicationInfo(a.info.applicationInfo, flags, state);
   7610             return a.info;
   7611         }
   7612         // Make shallow copies so we can store the metadata safely
   7613         ActivityInfo ai = new ActivityInfo(a.info);
   7614         ai.metaData = a.metaData;
   7615         ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
   7616         return ai;
   7617     }
   7618 
   7619     public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
   7620             PackageUserState state, int userId) {
   7621         if (ai == null) return null;
   7622         if (!checkUseInstalledOrHidden(flags, state, ai.applicationInfo)) {
   7623             return null;
   7624         }
   7625         // This is only used to return the ResolverActivity; we will just always
   7626         // make a copy.
   7627         ai = new ActivityInfo(ai);
   7628         ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
   7629         return ai;
   7630     }
   7631 
   7632     public final static class Service extends Component<ServiceIntentInfo> implements Parcelable {
   7633         public final ServiceInfo info;
   7634 
   7635         public Service(final ParseComponentArgs args, final ServiceInfo _info) {
   7636             super(args, _info);
   7637             info = _info;
   7638             info.applicationInfo = args.owner.applicationInfo;
   7639         }
   7640 
   7641         public void setPackageName(String packageName) {
   7642             super.setPackageName(packageName);
   7643             info.packageName = packageName;
   7644         }
   7645 
   7646         public String toString() {
   7647             StringBuilder sb = new StringBuilder(128);
   7648             sb.append("Service{");
   7649             sb.append(Integer.toHexString(System.identityHashCode(this)));
   7650             sb.append(' ');
   7651             appendComponentShortName(sb);
   7652             sb.append('}');
   7653             return sb.toString();
   7654         }
   7655 
   7656         @Override
   7657         public int describeContents() {
   7658             return 0;
   7659         }
   7660 
   7661         @Override
   7662         public void writeToParcel(Parcel dest, int flags) {
   7663             super.writeToParcel(dest, flags);
   7664             dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
   7665         }
   7666 
   7667         private Service(Parcel in) {
   7668             super(in);
   7669             info = in.readParcelable(Object.class.getClassLoader());
   7670 
   7671             for (ServiceIntentInfo aii : intents) {
   7672                 aii.service = this;
   7673                 order = Math.max(aii.getOrder(), order);
   7674             }
   7675 
   7676             if (info.permission != null) {
   7677                 info.permission = info.permission.intern();
   7678             }
   7679         }
   7680 
   7681         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Service>() {
   7682             public Service createFromParcel(Parcel in) {
   7683                 return new Service(in);
   7684             }
   7685 
   7686             public Service[] newArray(int size) {
   7687                 return new Service[size];
   7688             }
   7689         };
   7690     }
   7691 
   7692     public static final ServiceInfo generateServiceInfo(Service s, int flags,
   7693             PackageUserState state, int userId) {
   7694         if (s == null) return null;
   7695         if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) {
   7696             return null;
   7697         }
   7698         if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
   7699             updateApplicationInfo(s.info.applicationInfo, flags, state);
   7700             return s.info;
   7701         }
   7702         // Make shallow copies so we can store the metadata safely
   7703         ServiceInfo si = new ServiceInfo(s.info);
   7704         si.metaData = s.metaData;
   7705         si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
   7706         return si;
   7707     }
   7708 
   7709     public final static class Provider extends Component<ProviderIntentInfo> implements Parcelable {
   7710         public final ProviderInfo info;
   7711         public boolean syncable;
   7712 
   7713         public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
   7714             super(args, _info);
   7715             info = _info;
   7716             info.applicationInfo = args.owner.applicationInfo;
   7717             syncable = false;
   7718         }
   7719 
   7720         public Provider(Provider existingProvider) {
   7721             super(existingProvider);
   7722             this.info = existingProvider.info;
   7723             this.syncable = existingProvider.syncable;
   7724         }
   7725 
   7726         public void setPackageName(String packageName) {
   7727             super.setPackageName(packageName);
   7728             info.packageName = packageName;
   7729         }
   7730 
   7731         public String toString() {
   7732             StringBuilder sb = new StringBuilder(128);
   7733             sb.append("Provider{");
   7734             sb.append(Integer.toHexString(System.identityHashCode(this)));
   7735             sb.append(' ');
   7736             appendComponentShortName(sb);
   7737             sb.append('}');
   7738             return sb.toString();
   7739         }
   7740 
   7741         @Override
   7742         public int describeContents() {
   7743             return 0;
   7744         }
   7745 
   7746         @Override
   7747         public void writeToParcel(Parcel dest, int flags) {
   7748             super.writeToParcel(dest, flags);
   7749             dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
   7750             dest.writeInt((syncable) ? 1 : 0);
   7751         }
   7752 
   7753         private Provider(Parcel in) {
   7754             super(in);
   7755             info = in.readParcelable(Object.class.getClassLoader());
   7756             syncable = (in.readInt() == 1);
   7757 
   7758             for (ProviderIntentInfo aii : intents) {
   7759                 aii.provider = this;
   7760             }
   7761 
   7762             if (info.readPermission != null) {
   7763                 info.readPermission = info.readPermission.intern();
   7764             }
   7765 
   7766             if (info.writePermission != null) {
   7767                 info.writePermission = info.writePermission.intern();
   7768             }
   7769 
   7770             if (info.authority != null) {
   7771                 info.authority = info.authority.intern();
   7772             }
   7773         }
   7774 
   7775         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Provider>() {
   7776             public Provider createFromParcel(Parcel in) {
   7777                 return new Provider(in);
   7778             }
   7779 
   7780             public Provider[] newArray(int size) {
   7781                 return new Provider[size];
   7782             }
   7783         };
   7784     }
   7785 
   7786     public static final ProviderInfo generateProviderInfo(Provider p, int flags,
   7787             PackageUserState state, int userId) {
   7788         if (p == null) return null;
   7789         if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) {
   7790             return null;
   7791         }
   7792         if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
   7793                 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
   7794                         || p.info.uriPermissionPatterns == null)) {
   7795             updateApplicationInfo(p.info.applicationInfo, flags, state);
   7796             return p.info;
   7797         }
   7798         // Make shallow copies so we can store the metadata safely
   7799         ProviderInfo pi = new ProviderInfo(p.info);
   7800         pi.metaData = p.metaData;
   7801         if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
   7802             pi.uriPermissionPatterns = null;
   7803         }
   7804         pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
   7805         return pi;
   7806     }
   7807 
   7808     public final static class Instrumentation extends Component<IntentInfo> implements
   7809             Parcelable {
   7810         public final InstrumentationInfo info;
   7811 
   7812         public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
   7813             super(args, _info);
   7814             info = _info;
   7815         }
   7816 
   7817         public void setPackageName(String packageName) {
   7818             super.setPackageName(packageName);
   7819             info.packageName = packageName;
   7820         }
   7821 
   7822         public String toString() {
   7823             StringBuilder sb = new StringBuilder(128);
   7824             sb.append("Instrumentation{");
   7825             sb.append(Integer.toHexString(System.identityHashCode(this)));
   7826             sb.append(' ');
   7827             appendComponentShortName(sb);
   7828             sb.append('}');
   7829             return sb.toString();
   7830         }
   7831 
   7832         @Override
   7833         public int describeContents() {
   7834             return 0;
   7835         }
   7836 
   7837         @Override
   7838         public void writeToParcel(Parcel dest, int flags) {
   7839             super.writeToParcel(dest, flags);
   7840             dest.writeParcelable(info, flags);
   7841         }
   7842 
   7843         private Instrumentation(Parcel in) {
   7844             super(in);
   7845             info = in.readParcelable(Object.class.getClassLoader());
   7846 
   7847             if (info.targetPackage != null) {
   7848                 info.targetPackage = info.targetPackage.intern();
   7849             }
   7850 
   7851             if (info.targetProcesses != null) {
   7852                 info.targetProcesses = info.targetProcesses.intern();
   7853             }
   7854         }
   7855 
   7856         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Instrumentation>() {
   7857             public Instrumentation createFromParcel(Parcel in) {
   7858                 return new Instrumentation(in);
   7859             }
   7860 
   7861             public Instrumentation[] newArray(int size) {
   7862                 return new Instrumentation[size];
   7863             }
   7864         };
   7865     }
   7866 
   7867     public static final InstrumentationInfo generateInstrumentationInfo(
   7868             Instrumentation i, int flags) {
   7869         if (i == null) return null;
   7870         if ((flags&PackageManager.GET_META_DATA) == 0) {
   7871             return i.info;
   7872         }
   7873         InstrumentationInfo ii = new InstrumentationInfo(i.info);
   7874         ii.metaData = i.metaData;
   7875         return ii;
   7876     }
   7877 
   7878     public static abstract class IntentInfo extends IntentFilter {
   7879         public boolean hasDefault;
   7880         public int labelRes;
   7881         public CharSequence nonLocalizedLabel;
   7882         public int icon;
   7883         public int logo;
   7884         public int banner;
   7885         public int preferred;
   7886 
   7887         protected IntentInfo() {
   7888         }
   7889 
   7890         protected IntentInfo(Parcel dest) {
   7891             super(dest);
   7892             hasDefault = (dest.readInt() == 1);
   7893             labelRes = dest.readInt();
   7894             nonLocalizedLabel = dest.readCharSequence();
   7895             icon = dest.readInt();
   7896             logo = dest.readInt();
   7897             banner = dest.readInt();
   7898             preferred = dest.readInt();
   7899         }
   7900 
   7901 
   7902         public void writeIntentInfoToParcel(Parcel dest, int flags) {
   7903             super.writeToParcel(dest, flags);
   7904             dest.writeInt(hasDefault ? 1 : 0);
   7905             dest.writeInt(labelRes);
   7906             dest.writeCharSequence(nonLocalizedLabel);
   7907             dest.writeInt(icon);
   7908             dest.writeInt(logo);
   7909             dest.writeInt(banner);
   7910             dest.writeInt(preferred);
   7911         }
   7912     }
   7913 
   7914     public final static class ActivityIntentInfo extends IntentInfo {
   7915         public Activity activity;
   7916 
   7917         public ActivityIntentInfo(Activity _activity) {
   7918             activity = _activity;
   7919         }
   7920 
   7921         public String toString() {
   7922             StringBuilder sb = new StringBuilder(128);
   7923             sb.append("ActivityIntentInfo{");
   7924             sb.append(Integer.toHexString(System.identityHashCode(this)));
   7925             sb.append(' ');
   7926             activity.appendComponentShortName(sb);
   7927             sb.append('}');
   7928             return sb.toString();
   7929         }
   7930 
   7931         public ActivityIntentInfo(Parcel in) {
   7932             super(in);
   7933         }
   7934     }
   7935 
   7936     public final static class ServiceIntentInfo extends IntentInfo {
   7937         public Service service;
   7938 
   7939         public ServiceIntentInfo(Service _service) {
   7940             service = _service;
   7941         }
   7942 
   7943         public String toString() {
   7944             StringBuilder sb = new StringBuilder(128);
   7945             sb.append("ServiceIntentInfo{");
   7946             sb.append(Integer.toHexString(System.identityHashCode(this)));
   7947             sb.append(' ');
   7948             service.appendComponentShortName(sb);
   7949             sb.append('}');
   7950             return sb.toString();
   7951         }
   7952 
   7953         public ServiceIntentInfo(Parcel in) {
   7954             super(in);
   7955         }
   7956     }
   7957 
   7958     public static final class ProviderIntentInfo extends IntentInfo {
   7959         public Provider provider;
   7960 
   7961         public ProviderIntentInfo(Provider provider) {
   7962             this.provider = provider;
   7963         }
   7964 
   7965         public String toString() {
   7966             StringBuilder sb = new StringBuilder(128);
   7967             sb.append("ProviderIntentInfo{");
   7968             sb.append(Integer.toHexString(System.identityHashCode(this)));
   7969             sb.append(' ');
   7970             provider.appendComponentShortName(sb);
   7971             sb.append('}');
   7972             return sb.toString();
   7973         }
   7974 
   7975         public ProviderIntentInfo(Parcel in) {
   7976             super(in);
   7977         }
   7978     }
   7979 
   7980     /**
   7981      * @hide
   7982      */
   7983     public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
   7984         sCompatibilityModeEnabled = compatibilityModeEnabled;
   7985     }
   7986 
   7987     public static class PackageParserException extends Exception {
   7988         public final int error;
   7989 
   7990         public PackageParserException(int error, String detailMessage) {
   7991             super(detailMessage);
   7992             this.error = error;
   7993         }
   7994 
   7995         public PackageParserException(int error, String detailMessage, Throwable throwable) {
   7996             super(detailMessage, throwable);
   7997             this.error = error;
   7998         }
   7999     }
   8000 }
   8001