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