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