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