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 
NewPermissionInfo(String name, int sdkVersion, int fileVersion)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 
SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk)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 
ParsePackageItemArgs(Package _owner, String[] _outError, int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes, int _bannerRes)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 
ParseComponentArgs(Package _owner, String[] _outError, int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes, int _bannerRes, String[] _sepProcesses, int _processRes, int _descriptionRes, int _enabledRes)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 
PackageLite(String codePath, ApkLite baseApk, String[] splitNames, boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit, String[] splitCodePaths, int[] splitRevisionCodes)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 
getAllCodePaths()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 
ApkLite(String codePath, String packageName, String splitName, boolean isFeatureSplit, String configForSplit, String usesSplitName, int versionCode, int versionCodeMajor, int revisionCode, int installLocation, List<VerifierInfo> verifiers, SigningDetails signingDetails, boolean coreApp, boolean debuggable, boolean multiArch, boolean use32bitAbi, boolean extractNativeLibs, boolean isolatedSplits)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 
getLongVersionCode()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 
PackageParser()543     public PackageParser() {
544         mMetrics = new DisplayMetrics();
545         mMetrics.setToDefaults();
546     }
547 
setSeparateProcesses(String[] procs)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      */
setOnlyCoreApps(boolean onlyCoreApps)557     public void setOnlyCoreApps(boolean onlyCoreApps) {
558         mOnlyCoreApps = onlyCoreApps;
559     }
560 
setDisplayMetrics(DisplayMetrics metrics)561     public void setDisplayMetrics(DisplayMetrics metrics) {
562         mMetrics = metrics;
563     }
564 
565     /**
566      * Sets the cache directory for this package parser.
567      */
setCacheDir(File cacheDir)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 {
hasFeature(String feature)577         boolean hasFeature(String feature);
getOverlayPaths(String targetPackageName, String targetPath)578         String[] getOverlayPaths(String targetPackageName, String targetPath);
getOverlayApks(String targetPackageName)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 
CallbackImpl(PackageManager pm)589         public CallbackImpl(PackageManager pm) {
590             mPm = pm;
591         }
592 
hasFeature(String feature)593         @Override public boolean hasFeature(String feature) {
594             return mPm.hasSystemFeature(feature);
595         }
596 
getOverlayPaths(String targetPackageName, String targetPath)597         @Override public String[] getOverlayPaths(String targetPackageName, String targetPath) {
598             return null;
599         }
600 
getOverlayApks(String targetPackageName)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      */
setCallback(Callback cb)609     public void setCallback(Callback cb) {
610         mCallback = cb;
611     }
612 
isApkFile(File file)613     public static final boolean isApkFile(File file) {
614         return isApkPath(file.getName());
615     }
616 
isApkPath(String path)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      */
generatePackageInfo(PackageParser.Package p, int gids[], int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state)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      */
checkUseInstalledOrHidden(int flags, PackageUserState state, ApplicationInfo appInfo)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 
isAvailable(PackageUserState state)649     public static boolean isAvailable(PackageUserState state) {
650         return checkUseInstalledOrHidden(0, state, null);
651     }
652 
generatePackageInfo(PackageParser.Package p, int gids[], int flags, long firstInstallTime, long lastUpdateTime, Set<String> grantedPermissions, PackageUserState state, int userId)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
compare(String lhs, String rhs)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      */
parsePackageLite(File packageFile, int flags)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 
parseMonolithicPackageLite(File packageFile, int flags)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 
parseClusterPackageLite(File packageDir, int flags)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      */
parsePackage(File packageFile, int flags, boolean useCaches)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      */
parsePackage(File packageFile, int flags)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      */
getCacheKey(File packageFile, int flags)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
fromCacheEntry(byte[] bytes)1049     protected Package fromCacheEntry(byte[] bytes) {
1050         return fromCacheEntryStatic(bytes);
1051     }
1052 
1053     /** static version of {@link #fromCacheEntry} for unit tests. */
1054     @VisibleForTesting
fromCacheEntryStatic(byte[] bytes)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
toCacheEntry(Package pkg)1073     protected byte[] toCacheEntry(Package pkg) {
1074         return toCacheEntryStatic(pkg);
1075 
1076     }
1077 
1078     /** static version of {@link #toCacheEntry} for unit tests. */
1079     @VisibleForTesting
toCacheEntryStatic(Package pkg)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      */
isCacheUpToDate(File packageFile, File cacheFile)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      */
getCachedResult(File packageFile, int flags)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      */
cacheResult(File packageFile, int flags, Package parsed)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      */
parseClusterPackage(File packageDir, int flags)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
parseMonolithicPackage(File apkFile, int flags)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 
parseBaseApk(File apkFile, AssetManager assets, int flags)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 
parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)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      */
parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags, int splitIndex, String[] outError)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. */
toSigningKeys(Signature[] 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      */
collectCertificates(Package pkg, boolean skipVerify)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 
collectCertificatesInternal(Package pkg, boolean skipVerify)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 
collectCertificates(Package pkg, File apkFile, boolean skipVerify)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 
newConfiguredAssetManager()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      */
parseApkLite(File apkFile, int flags)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      */
parseApkLite(FileDescriptor fd, String debugPathName, int flags)1565     public static ApkLite parseApkLite(FileDescriptor fd, String debugPathName, int flags)
1566             throws PackageParserException {
1567         return parseApkLiteInner(null, fd, debugPathName, flags);
1568     }
1569 
parseApkLiteInner(File apkFile, FileDescriptor fd, String debugPathName, int flags)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 
validateName(String name, boolean requireSeparator, boolean requireFilename)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 
parsePackageSplitNames(XmlPullParser parser, AttributeSet attrs)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 
parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs, SigningDetails signingDetails)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      */
parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser, int flags, String[] outError)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      */
parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags, String[] outError)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      */
parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res, XmlResourceParser parser, int flags, String[] outError)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 
checkOverlayRequiredSystemProperty(String propName, String propValue)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      */
adjustPackageToBeUnresizeableAndUnpipable(Package pkg)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
computeTargetSdkVersion(@ntRangefrom = 0) int targetVers, @Nullable String targetCode, @NonNull String[] platformSdkCodenames, @NonNull String[] outError, boolean forceCurrentDev)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
computeMinSdkVersion(@ntRangefrom = 1) int minVers, @Nullable String minCode, @IntRange(from = 1) int platformSdkVersion, @NonNull String[] platformSdkCodenames, @NonNull String[] outError)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 
parseUsesFeature(Resources res, AttributeSet attrs)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 
parseUsesStaticLibrary(Package pkg, Resources res, XmlResourceParser parser, String[] outError)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 
parseAdditionalCertificates(Resources resources, XmlResourceParser parser, String[] outError)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 
parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)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 
buildClassName(String pkg, CharSequence clsSeq, String[] outError)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 
buildCompoundName(String pkg, CharSequence procSeq, String type, String[] outError)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 
buildProcessName(String pkg, String defProc, CharSequence procSeq, int flags, String[] separateProcesses, String[] outError)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 
buildTaskAffinityName(String pkg, String defProc, CharSequence procSeq, String[] outError)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 
parseKeySets(Package owner, Resources res, XmlResourceParser parser, String[] outError)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 
parsePermissionGroup(Package owner, int flags, Resources res, XmlResourceParser parser, String[] outError)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 
parsePermission(Package owner, Resources res, XmlResourceParser parser, String[] outError)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 
parsePermissionTree(Package owner, Resources res, XmlResourceParser parser, String[] outError)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 
parseInstrumentation(Package owner, Resources res, XmlResourceParser parser, String[] outError)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      */
parseBaseApplication(Package owner, Resources res, XmlResourceParser parser, int flags, String[] outError)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      */
hasDomainURLs(Package pkg)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      */
parseSplitApplication(Package owner, Resources res, XmlResourceParser parser, int flags, int splitIndex, String[] outError)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 
parsePackageItemInfo(Package owner, PackageItemInfo outInfo, String[] outError, String tag, TypedArray sa, boolean nameRequired, int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes)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 
parseActivity(Package owner, Resources res, XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs, boolean receiver, boolean hardwareAccelerated)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 
setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package owner)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      */
setMaxAspectRatio(Package owner)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 
parseProvider(Package owner, Resources res, XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs)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 
parseProviderTags(Resources res, XmlResourceParser parser, boolean visibleToEphemeral, Provider outInfo, String[] outError)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 
parseService(Package owner, Resources res, XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs)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 
isImplicitlyExposedIntent(IntentInfo intent)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 
parseAllMetaData(Resources res, XmlResourceParser parser, String tag, Component<?> outInfo, String[] outError)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 
parseMetaData(Resources res, XmlResourceParser parser, Bundle data, String[] outError)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 
parseVerifier(AttributeSet attrs)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 
parsePublicKey(final String encodedPublicKey)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 
parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs, boolean allowAutoVerify, IntentInfo outInfo, String[] outError)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
SigningDetails(Signature[] signatures, @SignatureSchemeVersion int signatureSchemeVersion, ArraySet<PublicKey> keys, Signature[] pastSigningCertificates, int[] pastSigningCertificatesFlags)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 
SigningDetails(Signature[] signatures, @SignatureSchemeVersion int signatureSchemeVersion, Signature[] pastSigningCertificates, int[] pastSigningCertificatesFlags)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 
SigningDetails(Signature[] signatures, @SignatureSchemeVersion int signatureSchemeVersion)5755         public SigningDetails(Signature[] signatures,
5756                 @SignatureSchemeVersion int signatureSchemeVersion)
5757                 throws CertificateException {
5758             this(signatures, signatureSchemeVersion,
5759                     null, null);
5760         }
5761 
SigningDetails(SigningDetails orig)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. */
hasSignatures()5788         public boolean hasSignatures() {
5789             return signatures != null && signatures.length > 0;
5790         }
5791 
5792         /** Returns true if the signing details have past signing certificates. */
hasPastSigningCertificates()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          */
hasAncestorOrSelf(SigningDetails oldDetails)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          */
hasAncestor(SigningDetails oldDetails)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          */
checkCapability(SigningDetails oldDetails, @CertCapabilities int flags)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          */
checkCapabilityRecover(SigningDetails oldDetails, @CertCapabilities int flags)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          */
hasCertificate(Signature signature)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          */
hasCertificate(Signature signature, @CertCapabilities int flags)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. */
hasCertificate(byte[] certificate)5917         public boolean hasCertificate(byte[] certificate) {
5918             Signature signature = new Signature(certificate);
5919             return hasCertificate(signature);
5920         }
5921 
hasCertificateInternal(Signature signature, int flags)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          */
checkCapability(String sha256String, @CertCapabilities int flags)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          */
hasSha256Certificate(byte[] sha256Certificate)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          */
hasSha256Certificate(byte[] sha256Certificate, @CertCapabilities int flags)6002         public boolean hasSha256Certificate(byte[] sha256Certificate, @CertCapabilities int flags) {
6003             return hasSha256CertificateInternal(sha256Certificate, flags);
6004         }
6005 
hasSha256CertificateInternal(byte[] sha256Certificate, int flags)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. */
signaturesMatchExactly(SigningDetails other)6036         public boolean signaturesMatchExactly(SigningDetails other) {
6037             return Signature.areExactMatch(this.signatures, other.signatures);
6038         }
6039 
6040         @Override
describeContents()6041         public int describeContents() {
6042             return 0;
6043         }
6044 
6045         @Override
writeToParcel(Parcel dest, int flags)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 
SigningDetails(Parcel in)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
equals(Object o)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
hashCode()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 
Builder()6130             public Builder() {
6131             }
6132 
6133             /** get signing certificates used to sign the current APK */
setSignatures(Signature[] signatures)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 */
setSignatureSchemeVersion(int signatureSchemeVersion)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 */
setPastSigningCertificates(Signature[] pastSigningCertificates)6146             public Builder setPastSigningCertificates(Signature[] pastSigningCertificates) {
6147                 mPastSigningCertificates = pastSigningCertificates;
6148                 return this;
6149             }
6150 
6151             /** set the flags for the {@code pastSigningCertificates} */
setPastSigningCertificatesFlags(int[] pastSigningCertificatesFlags)6152             public Builder setPastSigningCertificatesFlags(int[] pastSigningCertificatesFlags) {
6153                 mPastSigningCertificatesFlags = pastSigningCertificatesFlags;
6154                 return this;
6155             }
6156 
checkInvariants()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 */
build()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.
getLongVersionCode()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 
Package(String packageName)6373         public Package(String packageName) {
6374             this.packageName = packageName;
6375             this.manifestPackageName = packageName;
6376             applicationInfo.packageName = packageName;
6377             applicationInfo.uid = -1;
6378         }
6379 
setApplicationVolumeUuid(String volumeUuid)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 
setApplicationInfoCodePath(String codePath)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
setApplicationInfoResourcePath(String resourcePath)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
setApplicationInfoBaseResourcePath(String resourcePath)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 
setApplicationInfoBaseCodePath(String baseCodePath)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 
getChildPackageNames()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 
hasChildPackage(String packageName)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 
setApplicationInfoSplitCodePaths(String[] splitCodePaths)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
setApplicationInfoSplitResourcePaths(String[] resroucePaths)6467         public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) {
6468             this.applicationInfo.setSplitResourcePaths(resroucePaths);
6469             // Children have no splits
6470         }
6471 
setSplitCodePaths(String[] codePaths)6472         public void setSplitCodePaths(String[] codePaths) {
6473             this.splitCodePaths = codePaths;
6474         }
6475 
setCodePath(String codePath)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 
setBaseCodePath(String baseCodePath)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. */
setSigningDetails(@onNull SigningDetails signingDetails)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 
setVolumeUuid(String volumeUuid)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 
setApplicationInfoFlags(int mask, int flags)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 
setUse32bitAbi(boolean use32bitAbi)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 
isLibrary()6538         public boolean isLibrary() {
6539             return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames);
6540         }
6541 
getAllCodePaths()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          */
getAllCodePathsExcludingResourceOnly()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 
setPackageName(String newName)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 
hasComponentClassName(String name)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 */
isExternal()6626         public boolean isExternal() {
6627             return applicationInfo.isExternal();
6628         }
6629 
6630         /** @hide */
isForwardLocked()6631         public boolean isForwardLocked() {
6632             return applicationInfo.isForwardLocked();
6633         }
6634 
6635         /** @hide */
isOem()6636         public boolean isOem() {
6637             return applicationInfo.isOem();
6638         }
6639 
6640         /** @hide */
isVendor()6641         public boolean isVendor() {
6642             return applicationInfo.isVendor();
6643         }
6644 
6645         /** @hide */
isProduct()6646         public boolean isProduct() {
6647             return applicationInfo.isProduct();
6648         }
6649 
6650         /** @hide */
isPrivileged()6651         public boolean isPrivileged() {
6652             return applicationInfo.isPrivilegedApp();
6653         }
6654 
6655         /** @hide */
isSystem()6656         public boolean isSystem() {
6657             return applicationInfo.isSystemApp();
6658         }
6659 
6660         /** @hide */
isUpdatedSystemApp()6661         public boolean isUpdatedSystemApp() {
6662             return applicationInfo.isUpdatedSystemApp();
6663         }
6664 
6665         /** @hide */
canHaveOatDir()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 
isMatch(int flags)6674         public boolean isMatch(int flags) {
6675             if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
6676                 return isSystem();
6677             }
6678             return true;
6679         }
6680 
getLatestPackageUseTimeInMills()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 
getLatestForegroundPackageUseTimeInMills()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 
toString()6702         public String toString() {
6703             return "Package{"
6704                 + Integer.toHexString(System.identityHashCode(this))
6705                 + " " + packageName + "}";
6706         }
6707 
6708         @Override
describeContents()6709         public int describeContents() {
6710             return 0;
6711         }
6712 
Package(Parcel dest)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 
internStringArrayList(List<String> list)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          */
fixupOwner(List<? extends Component<?>> list)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
writeToParcel(Parcel dest, int flags)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          */
writeKeySetMapping( Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping)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          */
readKeySetMapping(Parcel in)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 
Component(Package _owner)7069         public Component(Package _owner) {
7070             owner = _owner;
7071             intents = null;
7072             className = null;
7073         }
7074 
Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo)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 
Component(final ParseComponentArgs args, final ComponentInfo outInfo)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 
Component(Component<II> clone)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 
getComponentName()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 
Component(Parcel in)7135         protected Component(Parcel in) {
7136             className = in.readString();
7137             metaData = in.readBundle();
7138             intents = createIntentsList(in);
7139 
7140             owner = null;
7141         }
7142 
writeToParcel(Parcel dest, int flags)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          */
writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out, int flags)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 
createIntentsList(Parcel in)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 
appendComponentShortName(StringBuilder sb)7212         public void appendComponentShortName(StringBuilder sb) {
7213             ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
7214         }
7215 
printComponentShortName(PrintWriter pw)7216         public void printComponentShortName(PrintWriter pw) {
7217             ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
7218         }
7219 
setPackageName(String packageName)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 
Permission(Package _owner)7231         public Permission(Package _owner) {
7232             super(_owner);
7233             info = new PermissionInfo();
7234         }
7235 
Permission(Package _owner, PermissionInfo _info)7236         public Permission(Package _owner, PermissionInfo _info) {
7237             super(_owner);
7238             info = _info;
7239         }
7240 
setPackageName(String packageName)7241         public void setPackageName(String packageName) {
7242             super.setPackageName(packageName);
7243             info.packageName = packageName;
7244         }
7245 
toString()7246         public String toString() {
7247             return "Permission{"
7248                 + Integer.toHexString(System.identityHashCode(this))
7249                 + " " + info.name + "}";
7250         }
7251 
7252         @Override
describeContents()7253         public int describeContents() {
7254             return 0;
7255         }
7256 
7257         @Override
writeToParcel(Parcel dest, int flags)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 */
isAppOp()7266         public boolean isAppOp() {
7267             return info.isAppOp();
7268         }
7269 
Permission(Parcel in)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 
PermissionGroup(Package _owner)7296         public PermissionGroup(Package _owner) {
7297             super(_owner);
7298             info = new PermissionGroupInfo();
7299         }
7300 
PermissionGroup(Package _owner, PermissionGroupInfo _info)7301         public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
7302             super(_owner);
7303             info = _info;
7304         }
7305 
setPackageName(String packageName)7306         public void setPackageName(String packageName) {
7307             super.setPackageName(packageName);
7308             info.packageName = packageName;
7309         }
7310 
toString()7311         public String toString() {
7312             return "PermissionGroup{"
7313                 + Integer.toHexString(System.identityHashCode(this))
7314                 + " " + info.name + "}";
7315         }
7316 
7317         @Override
describeContents()7318         public int describeContents() {
7319             return 0;
7320         }
7321 
7322         @Override
writeToParcel(Parcel dest, int flags)7323         public void writeToParcel(Parcel dest, int flags) {
7324             super.writeToParcel(dest, flags);
7325             dest.writeParcelable(info, flags);
7326         }
7327 
PermissionGroup(Parcel in)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 
copyNeeded(int flags, Package p, PackageUserState state, Bundle metaData, int userId)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 
generateApplicationInfo(Package p, int flags, PackageUserState state)7384     public static ApplicationInfo generateApplicationInfo(Package p, int flags,
7385             PackageUserState state) {
7386         return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
7387     }
7388 
updateApplicationInfo(ApplicationInfo ai, int flags, PackageUserState state)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 
generateApplicationInfo(Package p, int flags, PackageUserState state, int userId)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 
generateApplicationInfo(ApplicationInfo ai, int flags, PackageUserState state, int userId)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 
generatePermissionInfo( Permission p, int flags)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 
generatePermissionGroupInfo( PermissionGroup pg, int flags)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 
hasMaxAspectRatio()7522         private boolean hasMaxAspectRatio() {
7523             return mHasMaxAspectRatio;
7524         }
7525 
Activity(final ParseComponentArgs args, final ActivityInfo _info)7526         public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
7527             super(args, _info);
7528             info = _info;
7529             info.applicationInfo = args.owner.applicationInfo;
7530         }
7531 
setPackageName(String packageName)7532         public void setPackageName(String packageName) {
7533             super.setPackageName(packageName);
7534             info.packageName = packageName;
7535         }
7536 
7537 
setMaxAspectRatio(float maxAspectRatio)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 
toString()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
describeContents()7565         public int describeContents() {
7566             return 0;
7567         }
7568 
7569         @Override
writeToParcel(Parcel dest, int flags)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 
Activity(Parcel in)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 
generateActivityInfo(Activity a, int flags, PackageUserState state, int userId)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 
generateActivityInfo(ActivityInfo ai, int flags, PackageUserState state, int userId)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 
Service(final ParseComponentArgs args, final ServiceInfo _info)7635         public Service(final ParseComponentArgs args, final ServiceInfo _info) {
7636             super(args, _info);
7637             info = _info;
7638             info.applicationInfo = args.owner.applicationInfo;
7639         }
7640 
setPackageName(String packageName)7641         public void setPackageName(String packageName) {
7642             super.setPackageName(packageName);
7643             info.packageName = packageName;
7644         }
7645 
toString()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
describeContents()7657         public int describeContents() {
7658             return 0;
7659         }
7660 
7661         @Override
writeToParcel(Parcel dest, int flags)7662         public void writeToParcel(Parcel dest, int flags) {
7663             super.writeToParcel(dest, flags);
7664             dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
7665         }
7666 
Service(Parcel in)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 
generateServiceInfo(Service s, int flags, PackageUserState state, int userId)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 
Provider(final ParseComponentArgs args, final ProviderInfo _info)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 
Provider(Provider existingProvider)7720         public Provider(Provider existingProvider) {
7721             super(existingProvider);
7722             this.info = existingProvider.info;
7723             this.syncable = existingProvider.syncable;
7724         }
7725 
setPackageName(String packageName)7726         public void setPackageName(String packageName) {
7727             super.setPackageName(packageName);
7728             info.packageName = packageName;
7729         }
7730 
toString()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
describeContents()7742         public int describeContents() {
7743             return 0;
7744         }
7745 
7746         @Override
writeToParcel(Parcel dest, int flags)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 
Provider(Parcel in)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 
generateProviderInfo(Provider p, int flags, PackageUserState state, int userId)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 
Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info)7812         public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
7813             super(args, _info);
7814             info = _info;
7815         }
7816 
setPackageName(String packageName)7817         public void setPackageName(String packageName) {
7818             super.setPackageName(packageName);
7819             info.packageName = packageName;
7820         }
7821 
toString()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
describeContents()7833         public int describeContents() {
7834             return 0;
7835         }
7836 
7837         @Override
writeToParcel(Parcel dest, int flags)7838         public void writeToParcel(Parcel dest, int flags) {
7839             super.writeToParcel(dest, flags);
7840             dest.writeParcelable(info, flags);
7841         }
7842 
Instrumentation(Parcel in)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 
generateInstrumentationInfo( Instrumentation i, int flags)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 
IntentInfo()7887         protected IntentInfo() {
7888         }
7889 
IntentInfo(Parcel dest)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 
writeIntentInfoToParcel(Parcel dest, int flags)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 
ActivityIntentInfo(Activity _activity)7917         public ActivityIntentInfo(Activity _activity) {
7918             activity = _activity;
7919         }
7920 
toString()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 
ActivityIntentInfo(Parcel in)7931         public ActivityIntentInfo(Parcel in) {
7932             super(in);
7933         }
7934     }
7935 
7936     public final static class ServiceIntentInfo extends IntentInfo {
7937         public Service service;
7938 
ServiceIntentInfo(Service _service)7939         public ServiceIntentInfo(Service _service) {
7940             service = _service;
7941         }
7942 
toString()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 
ServiceIntentInfo(Parcel in)7953         public ServiceIntentInfo(Parcel in) {
7954             super(in);
7955         }
7956     }
7957 
7958     public static final class ProviderIntentInfo extends IntentInfo {
7959         public Provider provider;
7960 
ProviderIntentInfo(Provider provider)7961         public ProviderIntentInfo(Provider provider) {
7962             this.provider = provider;
7963         }
7964 
toString()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 
ProviderIntentInfo(Parcel in)7975         public ProviderIntentInfo(Parcel in) {
7976             super(in);
7977         }
7978     }
7979 
7980     /**
7981      * @hide
7982      */
setCompatibilityModeEnabled(boolean compatibilityModeEnabled)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 
PackageParserException(int error, String detailMessage)7990         public PackageParserException(int error, String detailMessage) {
7991             super(detailMessage);
7992             this.error = error;
7993         }
7994 
PackageParserException(int error, String detailMessage, Throwable throwable)7995         public PackageParserException(int error, String detailMessage, Throwable throwable) {
7996             super(detailMessage, throwable);
7997             this.error = error;
7998         }
7999     }
8000 }
8001