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.areExactMatch(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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1460                 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.areEffectiveMatch(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.areExactMatch(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.areExactMatch(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.areExactMatch() because order matters with the past signing certs
6681             if (!Arrays.equals(pastSigningCertificates, that.pastSigningCertificates)) {
6682                 return false;
6683             }
6684             // The capabilities for the past signing certs must match as well.
6685             for (int i = 0; i < pastSigningCertificates.length; i++) {
6686                 if (pastSigningCertificates[i].getFlags()
6687                         != that.pastSigningCertificates[i].getFlags()) {
6688                     return false;
6689                 }
6690             }
6691             return true;
6692         }
6693 
6694         @Override
hashCode()6695         public int hashCode() {
6696             int result = +Arrays.hashCode(signatures);
6697             result = 31 * result + signatureSchemeVersion;
6698             result = 31 * result + (publicKeys != null ? publicKeys.hashCode() : 0);
6699             result = 31 * result + Arrays.hashCode(pastSigningCertificates);
6700             return result;
6701         }
6702 
6703         /**
6704          * Builder of {@code SigningDetails} instances.
6705          */
6706         public static class Builder {
6707             private Signature[] mSignatures;
6708             private int mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
6709             private Signature[] mPastSigningCertificates;
6710 
6711             @UnsupportedAppUsage
Builder()6712             public Builder() {
6713             }
6714 
6715             /** get signing certificates used to sign the current APK */
6716             @UnsupportedAppUsage
setSignatures(Signature[] signatures)6717             public Builder setSignatures(Signature[] signatures) {
6718                 mSignatures = signatures;
6719                 return this;
6720             }
6721 
6722             /** set the signature scheme version used to sign the APK */
6723             @UnsupportedAppUsage
setSignatureSchemeVersion(int signatureSchemeVersion)6724             public Builder setSignatureSchemeVersion(int signatureSchemeVersion) {
6725                 mSignatureSchemeVersion = signatureSchemeVersion;
6726                 return this;
6727             }
6728 
6729             /** set the signing certificates by which the APK proved it can be authenticated */
6730             @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
setPastSigningCertificates(Signature[] pastSigningCertificates)6731             public Builder setPastSigningCertificates(Signature[] pastSigningCertificates) {
6732                 mPastSigningCertificates = pastSigningCertificates;
6733                 return this;
6734             }
6735 
checkInvariants()6736             private void checkInvariants() {
6737                 // must have signatures and scheme version set
6738                 if (mSignatures == null) {
6739                     throw new IllegalStateException("SigningDetails requires the current signing"
6740                             + " certificates.");
6741                 }
6742             }
6743             /** build a {@code SigningDetails} object */
6744             @UnsupportedAppUsage
build()6745             public SigningDetails build()
6746                     throws CertificateException {
6747                 checkInvariants();
6748                 return new SigningDetails(mSignatures, mSignatureSchemeVersion,
6749                         mPastSigningCertificates);
6750             }
6751         }
6752     }
6753 
6754     /**
6755      * Representation of a full package parsed from APK files on disk. A package
6756      * consists of a single base APK, and zero or more split APKs.
6757      *
6758      * Deprecated internally. Use AndroidPackage instead.
6759      */
6760     public final static class Package implements Parcelable {
6761 
6762         @UnsupportedAppUsage
6763         public String packageName;
6764 
6765         // The package name declared in the manifest as the package can be
6766         // renamed, for example static shared libs use synthetic package names.
6767         public String manifestPackageName;
6768 
6769         /** Names of any split APKs, ordered by parsed splitName */
6770         public String[] splitNames;
6771 
6772         // TODO: work towards making these paths invariant
6773 
6774         public String volumeUuid;
6775 
6776         /**
6777          * Path where this package was found on disk. For monolithic packages
6778          * this is path to single base APK file; for cluster packages this is
6779          * path to the cluster directory.
6780          */
6781         public String codePath;
6782 
6783         /** Path of base APK */
6784         public String baseCodePath;
6785         /** Paths of any split APKs, ordered by parsed splitName */
6786         public String[] splitCodePaths;
6787 
6788         /** Revision code of base APK */
6789         public int baseRevisionCode;
6790         /** Revision codes of any split APKs, ordered by parsed splitName */
6791         public int[] splitRevisionCodes;
6792 
6793         /** Flags of any split APKs; ordered by parsed splitName */
6794         public int[] splitFlags;
6795 
6796         /**
6797          * Private flags of any split APKs; ordered by parsed splitName.
6798          *
6799          * {@hide}
6800          */
6801         public int[] splitPrivateFlags;
6802 
6803         public boolean baseHardwareAccelerated;
6804 
6805         // For now we only support one application per package.
6806         @UnsupportedAppUsage
6807         public ApplicationInfo applicationInfo = new ApplicationInfo();
6808 
6809         @UnsupportedAppUsage
6810         public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
6811         @UnsupportedAppUsage
6812         public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
6813         @UnsupportedAppUsage
6814         public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
6815         @UnsupportedAppUsage
6816         public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
6817         @UnsupportedAppUsage
6818         public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
6819         @UnsupportedAppUsage
6820         public final ArrayList<Service> services = new ArrayList<Service>(0);
6821         @UnsupportedAppUsage
6822         public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
6823 
6824         @UnsupportedAppUsage
6825         public final ArrayList<String> requestedPermissions = new ArrayList<String>();
6826 
6827         /** Permissions requested but not in the manifest. */
6828         public final ArrayList<String> implicitPermissions = new ArrayList<>();
6829 
6830         @UnsupportedAppUsage
6831         public ArrayList<String> protectedBroadcasts;
6832 
6833         public Package parentPackage;
6834         public ArrayList<Package> childPackages;
6835 
6836         public String staticSharedLibName = null;
6837         public long staticSharedLibVersion = 0;
6838         public ArrayList<String> libraryNames = null;
6839         @UnsupportedAppUsage
6840         public ArrayList<String> usesLibraries = null;
6841         public ArrayList<String> usesStaticLibraries = null;
6842         public long[] usesStaticLibrariesVersions = null;
6843         public String[][] usesStaticLibrariesCertDigests = null;
6844         @UnsupportedAppUsage
6845         public ArrayList<String> usesOptionalLibraries = null;
6846         @UnsupportedAppUsage
6847         public String[] usesLibraryFiles = null;
6848         public ArrayList<SharedLibraryInfo> usesLibraryInfos = null;
6849 
6850         public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
6851 
6852         public ArrayList<String> mOriginalPackages = null;
6853         public String mRealPackage = null;
6854         public ArrayList<String> mAdoptPermissions = null;
6855 
6856         // We store the application meta-data independently to avoid multiple unwanted references
6857         @UnsupportedAppUsage
6858         public Bundle mAppMetaData = null;
6859 
6860         // The version code declared for this package.
6861         @UnsupportedAppUsage
6862         public int mVersionCode;
6863 
6864         // The major version code declared for this package.
6865         public int mVersionCodeMajor;
6866 
6867         // Return long containing mVersionCode and mVersionCodeMajor.
getLongVersionCode()6868         public long getLongVersionCode() {
6869             return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
6870         }
6871 
6872         // The version name declared for this package.
6873         @UnsupportedAppUsage
6874         public String mVersionName;
6875 
6876         // The shared user id that this package wants to use.
6877         @UnsupportedAppUsage
6878         public String mSharedUserId;
6879 
6880         // The shared user label that this package wants to use.
6881         @UnsupportedAppUsage
6882         public int mSharedUserLabel;
6883 
6884         // Signatures that were read from the package.
6885         @UnsupportedAppUsage
6886         @NonNull public SigningDetails mSigningDetails = SigningDetails.UNKNOWN;
6887 
6888         // For use by package manager service for quick lookup of
6889         // preferred up order.
6890         @UnsupportedAppUsage
6891         public int mPreferredOrder = 0;
6892 
6893         // For use by package manager to keep track of when a package was last used.
6894         public long[] mLastPackageUsageTimeInMills =
6895                 new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
6896 
6897         // // User set enabled state.
6898         // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
6899         //
6900         // // Whether the package has been stopped.
6901         // public boolean mSetStopped = false;
6902 
6903         // Additional data supplied by callers.
6904         @UnsupportedAppUsage
6905         public Object mExtras;
6906 
6907         // Applications hardware preferences
6908         @UnsupportedAppUsage
6909         public ArrayList<ConfigurationInfo> configPreferences = null;
6910 
6911         // Applications requested features
6912         @UnsupportedAppUsage
6913         public ArrayList<FeatureInfo> reqFeatures = null;
6914 
6915         // Applications requested feature groups
6916         public ArrayList<FeatureGroupInfo> featureGroups = null;
6917 
6918         @UnsupportedAppUsage
6919         public int installLocation;
6920 
6921         public boolean coreApp;
6922 
6923         /* An app that's required for all users and cannot be uninstalled for a user */
6924         public boolean mRequiredForAllUsers;
6925 
6926         /* The restricted account authenticator type that is used by this application */
6927         public String mRestrictedAccountType;
6928 
6929         /* The required account type without which this application will not function */
6930         public String mRequiredAccountType;
6931 
6932         public String mOverlayTarget;
6933         public String mOverlayTargetName;
6934         public String mOverlayCategory;
6935         public int mOverlayPriority;
6936         public boolean mOverlayIsStatic;
6937 
6938         public int mCompileSdkVersion;
6939         public String mCompileSdkVersionCodename;
6940 
6941         /**
6942          * Data used to feed the KeySetManagerService
6943          */
6944         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
6945         public ArraySet<String> mUpgradeKeySets;
6946         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
6947         public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
6948 
6949         /**
6950          * The install time abi override for this package, if any.
6951          *
6952          * TODO: This seems like a horrible place to put the abiOverride because
6953          * this isn't something the packageParser parsers. However, this fits in with
6954          * the rest of the PackageManager where package scanning randomly pushes
6955          * and prods fields out of {@code this.applicationInfo}.
6956          */
6957         public String cpuAbiOverride;
6958         /**
6959          * The install time abi override to choose 32bit abi's when multiple abi's
6960          * are present. This is only meaningfull for multiarch applications.
6961          * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
6962          */
6963         public boolean use32bitAbi;
6964 
6965         public byte[] restrictUpdateHash;
6966 
6967         /** Set if the app or any of its components are visible to instant applications. */
6968         public boolean visibleToInstantApps;
6969         /** Whether or not the package is a stub and must be replaced by the full version. */
6970         public boolean isStub;
6971 
6972         @UnsupportedAppUsage
Package(String packageName)6973         public Package(String packageName) {
6974             this.packageName = packageName;
6975             this.manifestPackageName = packageName;
6976             applicationInfo.packageName = packageName;
6977             applicationInfo.uid = -1;
6978         }
6979 
setApplicationVolumeUuid(String volumeUuid)6980         public void setApplicationVolumeUuid(String volumeUuid) {
6981             final UUID storageUuid = StorageManager.convert(volumeUuid);
6982             this.applicationInfo.volumeUuid = volumeUuid;
6983             this.applicationInfo.storageUuid = storageUuid;
6984             if (childPackages != null) {
6985                 final int packageCount = childPackages.size();
6986                 for (int i = 0; i < packageCount; i++) {
6987                     childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
6988                     childPackages.get(i).applicationInfo.storageUuid = storageUuid;
6989                 }
6990             }
6991         }
6992 
setApplicationInfoCodePath(String codePath)6993         public void setApplicationInfoCodePath(String codePath) {
6994             this.applicationInfo.setCodePath(codePath);
6995             if (childPackages != null) {
6996                 final int packageCount = childPackages.size();
6997                 for (int i = 0; i < packageCount; i++) {
6998                     childPackages.get(i).applicationInfo.setCodePath(codePath);
6999                 }
7000             }
7001         }
7002 
7003         /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
7004         @Deprecated
setApplicationInfoResourcePath(String resourcePath)7005         public void setApplicationInfoResourcePath(String resourcePath) {
7006             this.applicationInfo.setResourcePath(resourcePath);
7007             if (childPackages != null) {
7008                 final int packageCount = childPackages.size();
7009                 for (int i = 0; i < packageCount; i++) {
7010                     childPackages.get(i).applicationInfo.setResourcePath(resourcePath);
7011                 }
7012             }
7013         }
7014 
7015         /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
7016         @Deprecated
setApplicationInfoBaseResourcePath(String resourcePath)7017         public void setApplicationInfoBaseResourcePath(String resourcePath) {
7018             this.applicationInfo.setBaseResourcePath(resourcePath);
7019             if (childPackages != null) {
7020                 final int packageCount = childPackages.size();
7021                 for (int i = 0; i < packageCount; i++) {
7022                     childPackages.get(i).applicationInfo.setBaseResourcePath(resourcePath);
7023                 }
7024             }
7025         }
7026 
setApplicationInfoBaseCodePath(String baseCodePath)7027         public void setApplicationInfoBaseCodePath(String baseCodePath) {
7028             this.applicationInfo.setBaseCodePath(baseCodePath);
7029             if (childPackages != null) {
7030                 final int packageCount = childPackages.size();
7031                 for (int i = 0; i < packageCount; i++) {
7032                     childPackages.get(i).applicationInfo.setBaseCodePath(baseCodePath);
7033                 }
7034             }
7035         }
7036 
getChildPackageNames()7037         public List<String> getChildPackageNames() {
7038             if (childPackages == null) {
7039                 return null;
7040             }
7041             final int childCount = childPackages.size();
7042             final List<String> childPackageNames = new ArrayList<>(childCount);
7043             for (int i = 0; i < childCount; i++) {
7044                 String childPackageName = childPackages.get(i).packageName;
7045                 childPackageNames.add(childPackageName);
7046             }
7047             return childPackageNames;
7048         }
7049 
hasChildPackage(String packageName)7050         public boolean hasChildPackage(String packageName) {
7051             final int childCount = (childPackages != null) ? childPackages.size() : 0;
7052             for (int i = 0; i < childCount; i++) {
7053                 if (childPackages.get(i).packageName.equals(packageName)) {
7054                     return true;
7055                 }
7056             }
7057             return false;
7058         }
7059 
setApplicationInfoSplitCodePaths(String[] splitCodePaths)7060         public void setApplicationInfoSplitCodePaths(String[] splitCodePaths) {
7061             this.applicationInfo.setSplitCodePaths(splitCodePaths);
7062             // Children have no splits
7063         }
7064 
7065         /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
7066         @Deprecated
setApplicationInfoSplitResourcePaths(String[] resroucePaths)7067         public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) {
7068             this.applicationInfo.setSplitResourcePaths(resroucePaths);
7069             // Children have no splits
7070         }
7071 
setSplitCodePaths(String[] codePaths)7072         public void setSplitCodePaths(String[] codePaths) {
7073             this.splitCodePaths = codePaths;
7074         }
7075 
setCodePath(String codePath)7076         public void setCodePath(String codePath) {
7077             this.codePath = codePath;
7078             if (childPackages != null) {
7079                 final int packageCount = childPackages.size();
7080                 for (int i = 0; i < packageCount; i++) {
7081                     childPackages.get(i).codePath = codePath;
7082                 }
7083             }
7084         }
7085 
setBaseCodePath(String baseCodePath)7086         public void setBaseCodePath(String baseCodePath) {
7087             this.baseCodePath = baseCodePath;
7088             if (childPackages != null) {
7089                 final int packageCount = childPackages.size();
7090                 for (int i = 0; i < packageCount; i++) {
7091                     childPackages.get(i).baseCodePath = baseCodePath;
7092                 }
7093             }
7094         }
7095 
7096         /** Sets signing details on the package and any of its children. */
setSigningDetails(@onNull SigningDetails signingDetails)7097         public void setSigningDetails(@NonNull SigningDetails signingDetails) {
7098             mSigningDetails = signingDetails;
7099             if (childPackages != null) {
7100                 final int packageCount = childPackages.size();
7101                 for (int i = 0; i < packageCount; i++) {
7102                     childPackages.get(i).mSigningDetails = signingDetails;
7103                 }
7104             }
7105         }
7106 
setVolumeUuid(String volumeUuid)7107         public void setVolumeUuid(String volumeUuid) {
7108             this.volumeUuid = volumeUuid;
7109             if (childPackages != null) {
7110                 final int packageCount = childPackages.size();
7111                 for (int i = 0; i < packageCount; i++) {
7112                     childPackages.get(i).volumeUuid = volumeUuid;
7113                 }
7114             }
7115         }
7116 
setApplicationInfoFlags(int mask, int flags)7117         public void setApplicationInfoFlags(int mask, int flags) {
7118             applicationInfo.flags = (applicationInfo.flags & ~mask) | (mask & flags);
7119             if (childPackages != null) {
7120                 final int packageCount = childPackages.size();
7121                 for (int i = 0; i < packageCount; i++) {
7122                     childPackages.get(i).applicationInfo.flags =
7123                             (applicationInfo.flags & ~mask) | (mask & flags);
7124                 }
7125             }
7126         }
7127 
setUse32bitAbi(boolean use32bitAbi)7128         public void setUse32bitAbi(boolean use32bitAbi) {
7129             this.use32bitAbi = use32bitAbi;
7130             if (childPackages != null) {
7131                 final int packageCount = childPackages.size();
7132                 for (int i = 0; i < packageCount; i++) {
7133                     childPackages.get(i).use32bitAbi = use32bitAbi;
7134                 }
7135             }
7136         }
7137 
isLibrary()7138         public boolean isLibrary() {
7139             return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames);
7140         }
7141 
getAllCodePaths()7142         public List<String> getAllCodePaths() {
7143             ArrayList<String> paths = new ArrayList<>();
7144             paths.add(baseCodePath);
7145             if (!ArrayUtils.isEmpty(splitCodePaths)) {
7146                 Collections.addAll(paths, splitCodePaths);
7147             }
7148             return paths;
7149         }
7150 
7151         /**
7152          * Filtered set of {@link #getAllCodePaths()} that excludes
7153          * resource-only APKs.
7154          */
getAllCodePathsExcludingResourceOnly()7155         public List<String> getAllCodePathsExcludingResourceOnly() {
7156             ArrayList<String> paths = new ArrayList<>();
7157             if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
7158                 paths.add(baseCodePath);
7159             }
7160             if (!ArrayUtils.isEmpty(splitCodePaths)) {
7161                 for (int i = 0; i < splitCodePaths.length; i++) {
7162                     if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
7163                         paths.add(splitCodePaths[i]);
7164                     }
7165                 }
7166             }
7167             return paths;
7168         }
7169 
7170         @UnsupportedAppUsage
setPackageName(String newName)7171         public void setPackageName(String newName) {
7172             packageName = newName;
7173             applicationInfo.packageName = newName;
7174             for (int i=permissions.size()-1; i>=0; i--) {
7175                 permissions.get(i).setPackageName(newName);
7176             }
7177             for (int i=permissionGroups.size()-1; i>=0; i--) {
7178                 permissionGroups.get(i).setPackageName(newName);
7179             }
7180             for (int i=activities.size()-1; i>=0; i--) {
7181                 activities.get(i).setPackageName(newName);
7182             }
7183             for (int i=receivers.size()-1; i>=0; i--) {
7184                 receivers.get(i).setPackageName(newName);
7185             }
7186             for (int i=providers.size()-1; i>=0; i--) {
7187                 providers.get(i).setPackageName(newName);
7188             }
7189             for (int i=services.size()-1; i>=0; i--) {
7190                 services.get(i).setPackageName(newName);
7191             }
7192             for (int i=instrumentation.size()-1; i>=0; i--) {
7193                 instrumentation.get(i).setPackageName(newName);
7194             }
7195         }
7196 
hasComponentClassName(String name)7197         public boolean hasComponentClassName(String name) {
7198             for (int i=activities.size()-1; i>=0; i--) {
7199                 if (name.equals(activities.get(i).className)) {
7200                     return true;
7201                 }
7202             }
7203             for (int i=receivers.size()-1; i>=0; i--) {
7204                 if (name.equals(receivers.get(i).className)) {
7205                     return true;
7206                 }
7207             }
7208             for (int i=providers.size()-1; i>=0; i--) {
7209                 if (name.equals(providers.get(i).className)) {
7210                     return true;
7211                 }
7212             }
7213             for (int i=services.size()-1; i>=0; i--) {
7214                 if (name.equals(services.get(i).className)) {
7215                     return true;
7216                 }
7217             }
7218             for (int i=instrumentation.size()-1; i>=0; i--) {
7219                 if (name.equals(instrumentation.get(i).className)) {
7220                     return true;
7221                 }
7222             }
7223             return false;
7224         }
7225 
7226         /** @hide */
isExternal()7227         public boolean isExternal() {
7228             return applicationInfo.isExternal();
7229         }
7230 
7231         /** @hide */
isForwardLocked()7232         public boolean isForwardLocked() {
7233             return false;
7234         }
7235 
7236         /** @hide */
isOem()7237         public boolean isOem() {
7238             return applicationInfo.isOem();
7239         }
7240 
7241         /** @hide */
isVendor()7242         public boolean isVendor() {
7243             return applicationInfo.isVendor();
7244         }
7245 
7246         /** @hide */
isProduct()7247         public boolean isProduct() {
7248             return applicationInfo.isProduct();
7249         }
7250 
7251         /** @hide */
isSystemExt()7252         public boolean isSystemExt() {
7253             return applicationInfo.isSystemExt();
7254         }
7255 
7256         /** @hide */
isOdm()7257         public boolean isOdm() {
7258             return applicationInfo.isOdm();
7259         }
7260 
7261         /** @hide */
isPrivileged()7262         public boolean isPrivileged() {
7263             return applicationInfo.isPrivilegedApp();
7264         }
7265 
7266         /** @hide */
isSystem()7267         public boolean isSystem() {
7268             return applicationInfo.isSystemApp();
7269         }
7270 
7271         /** @hide */
isUpdatedSystemApp()7272         public boolean isUpdatedSystemApp() {
7273             return applicationInfo.isUpdatedSystemApp();
7274         }
7275 
7276         /** @hide */
canHaveOatDir()7277         public boolean canHaveOatDir() {
7278             // Nobody should be calling this method ever, but we can't rely on this.
7279             // Thus no logic here and a reasonable return value.
7280             return true;
7281         }
7282 
isMatch(int flags)7283         public boolean isMatch(int flags) {
7284             if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
7285                 return isSystem();
7286             }
7287             return true;
7288         }
7289 
getLatestPackageUseTimeInMills()7290         public long getLatestPackageUseTimeInMills() {
7291             long latestUse = 0L;
7292             for (long use : mLastPackageUsageTimeInMills) {
7293                 latestUse = Math.max(latestUse, use);
7294             }
7295             return latestUse;
7296         }
7297 
getLatestForegroundPackageUseTimeInMills()7298         public long getLatestForegroundPackageUseTimeInMills() {
7299             int[] foregroundReasons = {
7300                 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
7301                 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
7302             };
7303 
7304             long latestUse = 0L;
7305             for (int reason : foregroundReasons) {
7306                 latestUse = Math.max(latestUse, mLastPackageUsageTimeInMills[reason]);
7307             }
7308             return latestUse;
7309         }
7310 
toString()7311         public String toString() {
7312             return "Package{"
7313                 + Integer.toHexString(System.identityHashCode(this))
7314                 + " " + packageName + "}";
7315         }
7316 
7317         @Override
describeContents()7318         public int describeContents() {
7319             return 0;
7320         }
7321 
Package(Parcel dest)7322         public Package(Parcel dest) {
7323             // We use the boot classloader for all classes that we load.
7324             final ClassLoader boot = Object.class.getClassLoader();
7325 
7326             packageName = dest.readString().intern();
7327             manifestPackageName = dest.readString();
7328             splitNames = dest.readStringArray();
7329             volumeUuid = dest.readString();
7330             codePath = dest.readString();
7331             baseCodePath = dest.readString();
7332             splitCodePaths = dest.readStringArray();
7333             baseRevisionCode = dest.readInt();
7334             splitRevisionCodes = dest.createIntArray();
7335             splitFlags = dest.createIntArray();
7336             splitPrivateFlags = dest.createIntArray();
7337             baseHardwareAccelerated = (dest.readInt() == 1);
7338             applicationInfo = dest.readParcelable(boot, android.content.pm.ApplicationInfo.class);
7339             if (applicationInfo.permission != null) {
7340                 applicationInfo.permission = applicationInfo.permission.intern();
7341             }
7342 
7343             // We don't serialize the "owner" package and the application info object for each of
7344             // these components, in order to save space and to avoid circular dependencies while
7345             // serialization. We need to fix them all up here.
7346             dest.readParcelableList(permissions, boot, android.content.pm.PackageParser.Permission.class);
7347             fixupOwner(permissions);
7348             dest.readParcelableList(permissionGroups, boot, android.content.pm.PackageParser.PermissionGroup.class);
7349             fixupOwner(permissionGroups);
7350             dest.readParcelableList(activities, boot, android.content.pm.PackageParser.Activity.class);
7351             fixupOwner(activities);
7352             dest.readParcelableList(receivers, boot, android.content.pm.PackageParser.Activity.class);
7353             fixupOwner(receivers);
7354             dest.readParcelableList(providers, boot, android.content.pm.PackageParser.Provider.class);
7355             fixupOwner(providers);
7356             dest.readParcelableList(services, boot, android.content.pm.PackageParser.Service.class);
7357             fixupOwner(services);
7358             dest.readParcelableList(instrumentation, boot, android.content.pm.PackageParser.Instrumentation.class);
7359             fixupOwner(instrumentation);
7360 
7361             dest.readStringList(requestedPermissions);
7362             internStringArrayList(requestedPermissions);
7363             dest.readStringList(implicitPermissions);
7364             internStringArrayList(implicitPermissions);
7365             protectedBroadcasts = dest.createStringArrayList();
7366             internStringArrayList(protectedBroadcasts);
7367 
7368             parentPackage = dest.readParcelable(boot, android.content.pm.PackageParser.Package.class);
7369 
7370             childPackages = new ArrayList<>();
7371             dest.readParcelableList(childPackages, boot, android.content.pm.PackageParser.Package.class);
7372             if (childPackages.size() == 0) {
7373                 childPackages = null;
7374             }
7375 
7376             staticSharedLibName = dest.readString();
7377             if (staticSharedLibName != null) {
7378                 staticSharedLibName = staticSharedLibName.intern();
7379             }
7380             staticSharedLibVersion = dest.readLong();
7381             libraryNames = dest.createStringArrayList();
7382             internStringArrayList(libraryNames);
7383             usesLibraries = dest.createStringArrayList();
7384             internStringArrayList(usesLibraries);
7385             usesOptionalLibraries = dest.createStringArrayList();
7386             internStringArrayList(usesOptionalLibraries);
7387             usesLibraryFiles = dest.readStringArray();
7388 
7389             usesLibraryInfos = dest.createTypedArrayList(SharedLibraryInfo.CREATOR);
7390 
7391             final int libCount = dest.readInt();
7392             if (libCount > 0) {
7393                 usesStaticLibraries = new ArrayList<>(libCount);
7394                 dest.readStringList(usesStaticLibraries);
7395                 internStringArrayList(usesStaticLibraries);
7396                 usesStaticLibrariesVersions = new long[libCount];
7397                 dest.readLongArray(usesStaticLibrariesVersions);
7398                 usesStaticLibrariesCertDigests = new String[libCount][];
7399                 for (int i = 0; i < libCount; i++) {
7400                     usesStaticLibrariesCertDigests[i] = dest.createStringArray();
7401                 }
7402             }
7403 
7404             preferredActivityFilters = new ArrayList<>();
7405             dest.readParcelableList(preferredActivityFilters, boot, android.content.pm.PackageParser.ActivityIntentInfo.class);
7406             if (preferredActivityFilters.size() == 0) {
7407                 preferredActivityFilters = null;
7408             }
7409 
7410             mOriginalPackages = dest.createStringArrayList();
7411             mRealPackage = dest.readString();
7412             mAdoptPermissions = dest.createStringArrayList();
7413             mAppMetaData = dest.readBundle();
7414             mVersionCode = dest.readInt();
7415             mVersionCodeMajor = dest.readInt();
7416             mVersionName = dest.readString();
7417             if (mVersionName != null) {
7418                 mVersionName = mVersionName.intern();
7419             }
7420             mSharedUserId = dest.readString();
7421             if (mSharedUserId != null) {
7422                 mSharedUserId = mSharedUserId.intern();
7423             }
7424             mSharedUserLabel = dest.readInt();
7425 
7426             mSigningDetails = dest.readParcelable(boot, android.content.pm.PackageParser.SigningDetails.class);
7427 
7428             mPreferredOrder = dest.readInt();
7429 
7430             // long[] packageUsageTimeMillis is not persisted because it isn't information that
7431             // is parsed from the APK.
7432 
7433             // Object mExtras is not persisted because it is not information that is read from
7434             // the APK, rather, it is supplied by callers.
7435 
7436 
7437             configPreferences = new ArrayList<>();
7438             dest.readParcelableList(configPreferences, boot, android.content.pm.ConfigurationInfo.class);
7439             if (configPreferences.size() == 0) {
7440                 configPreferences = null;
7441             }
7442 
7443             reqFeatures = new ArrayList<>();
7444             dest.readParcelableList(reqFeatures, boot, android.content.pm.FeatureInfo.class);
7445             if (reqFeatures.size() == 0) {
7446                 reqFeatures = null;
7447             }
7448 
7449             featureGroups = new ArrayList<>();
7450             dest.readParcelableList(featureGroups, boot, android.content.pm.FeatureGroupInfo.class);
7451             if (featureGroups.size() == 0) {
7452                 featureGroups = null;
7453             }
7454 
7455             installLocation = dest.readInt();
7456             coreApp = (dest.readInt() == 1);
7457             mRequiredForAllUsers = (dest.readInt() == 1);
7458             mRestrictedAccountType = dest.readString();
7459             mRequiredAccountType = dest.readString();
7460             mOverlayTarget = dest.readString();
7461             mOverlayTargetName = dest.readString();
7462             mOverlayCategory = dest.readString();
7463             mOverlayPriority = dest.readInt();
7464             mOverlayIsStatic = (dest.readInt() == 1);
7465             mCompileSdkVersion = dest.readInt();
7466             mCompileSdkVersionCodename = dest.readString();
7467             mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
7468 
7469             mKeySetMapping = readKeySetMapping(dest);
7470 
7471             cpuAbiOverride = dest.readString();
7472             use32bitAbi = (dest.readInt() == 1);
7473             restrictUpdateHash = dest.createByteArray();
7474             visibleToInstantApps = dest.readInt() == 1;
7475         }
7476 
internStringArrayList(List<String> list)7477         private static void internStringArrayList(List<String> list) {
7478             if (list != null) {
7479                 final int N = list.size();
7480                 for (int i = 0; i < N; ++i) {
7481                     list.set(i, list.get(i).intern());
7482                 }
7483             }
7484         }
7485 
7486         /**
7487          * Sets the package owner and the the {@code applicationInfo} for every component
7488          * owner by this package.
7489          */
fixupOwner(List<? extends Component<?>> list)7490         public void fixupOwner(List<? extends Component<?>> list) {
7491             if (list != null) {
7492                 for (Component<?> c : list) {
7493                     c.owner = this;
7494                     if (c instanceof Activity) {
7495                         ((Activity) c).info.applicationInfo = this.applicationInfo;
7496                     } else if (c instanceof Service) {
7497                         ((Service) c).info.applicationInfo = this.applicationInfo;
7498                     } else if (c instanceof Provider) {
7499                         ((Provider) c).info.applicationInfo = this.applicationInfo;
7500                     }
7501                 }
7502             }
7503         }
7504 
7505         @Override
writeToParcel(Parcel dest, int flags)7506         public void writeToParcel(Parcel dest, int flags) {
7507             dest.writeString(packageName);
7508             dest.writeString(manifestPackageName);
7509             dest.writeStringArray(splitNames);
7510             dest.writeString(volumeUuid);
7511             dest.writeString(codePath);
7512             dest.writeString(baseCodePath);
7513             dest.writeStringArray(splitCodePaths);
7514             dest.writeInt(baseRevisionCode);
7515             dest.writeIntArray(splitRevisionCodes);
7516             dest.writeIntArray(splitFlags);
7517             dest.writeIntArray(splitPrivateFlags);
7518             dest.writeInt(baseHardwareAccelerated ? 1 : 0);
7519             dest.writeParcelable(applicationInfo, flags);
7520 
7521             dest.writeParcelableList(permissions, flags);
7522             dest.writeParcelableList(permissionGroups, flags);
7523             dest.writeParcelableList(activities, flags);
7524             dest.writeParcelableList(receivers, flags);
7525             dest.writeParcelableList(providers, flags);
7526             dest.writeParcelableList(services, flags);
7527             dest.writeParcelableList(instrumentation, flags);
7528 
7529             dest.writeStringList(requestedPermissions);
7530             dest.writeStringList(implicitPermissions);
7531             dest.writeStringList(protectedBroadcasts);
7532 
7533             // TODO: This doesn't work: b/64295061
7534             dest.writeParcelable(parentPackage, flags);
7535             dest.writeParcelableList(childPackages, flags);
7536 
7537             dest.writeString(staticSharedLibName);
7538             dest.writeLong(staticSharedLibVersion);
7539             dest.writeStringList(libraryNames);
7540             dest.writeStringList(usesLibraries);
7541             dest.writeStringList(usesOptionalLibraries);
7542             dest.writeStringArray(usesLibraryFiles);
7543             dest.writeTypedList(usesLibraryInfos);
7544 
7545             if (ArrayUtils.isEmpty(usesStaticLibraries)) {
7546                 dest.writeInt(-1);
7547             } else {
7548                 dest.writeInt(usesStaticLibraries.size());
7549                 dest.writeStringList(usesStaticLibraries);
7550                 dest.writeLongArray(usesStaticLibrariesVersions);
7551                 for (String[] usesStaticLibrariesCertDigest : usesStaticLibrariesCertDigests) {
7552                     dest.writeStringArray(usesStaticLibrariesCertDigest);
7553                 }
7554             }
7555 
7556             dest.writeParcelableList(preferredActivityFilters, flags);
7557 
7558             dest.writeStringList(mOriginalPackages);
7559             dest.writeString(mRealPackage);
7560             dest.writeStringList(mAdoptPermissions);
7561             dest.writeBundle(mAppMetaData);
7562             dest.writeInt(mVersionCode);
7563             dest.writeInt(mVersionCodeMajor);
7564             dest.writeString(mVersionName);
7565             dest.writeString(mSharedUserId);
7566             dest.writeInt(mSharedUserLabel);
7567 
7568             dest.writeParcelable(mSigningDetails, flags);
7569 
7570             dest.writeInt(mPreferredOrder);
7571 
7572             // long[] packageUsageTimeMillis is not persisted because it isn't information that
7573             // is parsed from the APK.
7574 
7575             // Object mExtras is not persisted because it is not information that is read from
7576             // the APK, rather, it is supplied by callers.
7577 
7578             dest.writeParcelableList(configPreferences, flags);
7579             dest.writeParcelableList(reqFeatures, flags);
7580             dest.writeParcelableList(featureGroups, flags);
7581 
7582             dest.writeInt(installLocation);
7583             dest.writeInt(coreApp ? 1 : 0);
7584             dest.writeInt(mRequiredForAllUsers ? 1 : 0);
7585             dest.writeString(mRestrictedAccountType);
7586             dest.writeString(mRequiredAccountType);
7587             dest.writeString(mOverlayTarget);
7588             dest.writeString(mOverlayTargetName);
7589             dest.writeString(mOverlayCategory);
7590             dest.writeInt(mOverlayPriority);
7591             dest.writeInt(mOverlayIsStatic ? 1 : 0);
7592             dest.writeInt(mCompileSdkVersion);
7593             dest.writeString(mCompileSdkVersionCodename);
7594             dest.writeArraySet(mUpgradeKeySets);
7595             writeKeySetMapping(dest, mKeySetMapping);
7596             dest.writeString(cpuAbiOverride);
7597             dest.writeInt(use32bitAbi ? 1 : 0);
7598             dest.writeByteArray(restrictUpdateHash);
7599             dest.writeInt(visibleToInstantApps ? 1 : 0);
7600         }
7601 
7602         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
7603             public Package createFromParcel(Parcel in) {
7604                 return new Package(in);
7605             }
7606 
7607             public Package[] newArray(int size) {
7608                 return new Package[size];
7609             }
7610         };
7611     }
7612 
7613     public static abstract class Component<II extends IntentInfo> {
7614         @UnsupportedAppUsage
7615         public final ArrayList<II> intents;
7616         @UnsupportedAppUsage
7617         public final String className;
7618 
7619         @UnsupportedAppUsage
7620         public Bundle metaData;
7621         @UnsupportedAppUsage
7622         public Package owner;
7623         /** The order of this component in relation to its peers */
7624         public int order;
7625 
7626         ComponentName componentName;
7627         String componentShortName;
7628 
Component(Package owner, ArrayList<II> intents, String className)7629         public Component(Package owner, ArrayList<II> intents, String className) {
7630             this.owner = owner;
7631             this.intents = intents;
7632             this.className = className;
7633         }
7634 
Component(Package owner)7635         public Component(Package owner) {
7636             this.owner = owner;
7637             this.intents = null;
7638             this.className = null;
7639         }
7640 
Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo)7641         public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
7642             owner = args.owner;
7643             intents = new ArrayList<II>(0);
7644             if (parsePackageItemInfo(args.owner, outInfo, args.outError, args.tag, args.sa,
7645                     true /*nameRequired*/, args.nameRes, args.labelRes, args.iconRes,
7646                     args.roundIconRes, args.logoRes, args.bannerRes)) {
7647                 className = outInfo.name;
7648             } else {
7649                 className = null;
7650             }
7651         }
7652 
Component(final ParseComponentArgs args, final ComponentInfo outInfo)7653         public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
7654             this(args, (PackageItemInfo)outInfo);
7655             if (args.outError[0] != null) {
7656                 return;
7657             }
7658 
7659             if (args.processRes != 0) {
7660                 CharSequence pname;
7661                 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
7662                     pname = args.sa.getNonConfigurationString(args.processRes,
7663                             Configuration.NATIVE_CONFIG_VERSION);
7664                 } else {
7665                     // Some older apps have been seen to use a resource reference
7666                     // here that on older builds was ignored (with a warning).  We
7667                     // need to continue to do this for them so they don't break.
7668                     pname = args.sa.getNonResourceString(args.processRes);
7669                 }
7670                 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
7671                         owner.applicationInfo.processName, pname,
7672                         args.flags, args.sepProcesses, args.outError);
7673             }
7674 
7675             if (args.descriptionRes != 0) {
7676                 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
7677             }
7678 
7679             outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
7680         }
7681 
Component(Component<II> clone)7682         public Component(Component<II> clone) {
7683             owner = clone.owner;
7684             intents = clone.intents;
7685             className = clone.className;
7686             componentName = clone.componentName;
7687             componentShortName = clone.componentShortName;
7688         }
7689 
7690         @UnsupportedAppUsage
getComponentName()7691         public ComponentName getComponentName() {
7692             if (componentName != null) {
7693                 return componentName;
7694             }
7695             if (className != null) {
7696                 componentName = new ComponentName(owner.applicationInfo.packageName,
7697                         className);
7698             }
7699             return componentName;
7700         }
7701 
Component(Parcel in)7702         protected Component(Parcel in) {
7703             className = in.readString();
7704             metaData = in.readBundle();
7705             intents = createIntentsList(in);
7706 
7707             owner = null;
7708         }
7709 
writeToParcel(Parcel dest, int flags)7710         protected void writeToParcel(Parcel dest, int flags) {
7711             dest.writeString(className);
7712             dest.writeBundle(metaData);
7713 
7714             writeIntentsList(intents, dest, flags);
7715         }
7716 
7717         /**
7718          * <p>
7719          * Implementation note: The serialized form for the intent list also contains the name
7720          * of the concrete class that's stored in the list, and assumes that every element of the
7721          * list is of the same type. This is very similar to the original parcelable mechanism.
7722          * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable
7723          * and is public API. It also declares Parcelable related methods as final which means
7724          * we can't extend them. The approach of using composition instead of inheritance leads to
7725          * a large set of cascading changes in the PackageManagerService, which seem undesirable.
7726          *
7727          * <p>
7728          * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up
7729          * to make sure their owner fields are consistent. See {@code fixupOwner}.
7730          */
writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out, int flags)7731         private static void writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out,
7732                                              int flags) {
7733             if (list == null) {
7734                 out.writeInt(-1);
7735                 return;
7736             }
7737 
7738             final int N = list.size();
7739             out.writeInt(N);
7740 
7741             // Don't bother writing the component name if the list is empty.
7742             if (N > 0) {
7743                 IntentInfo info = list.get(0);
7744                 out.writeString(info.getClass().getName());
7745 
7746                 for (int i = 0; i < N;i++) {
7747                     list.get(i).writeIntentInfoToParcel(out, flags);
7748                 }
7749             }
7750         }
7751 
createIntentsList(Parcel in)7752         private static <T extends IntentInfo> ArrayList<T> createIntentsList(Parcel in) {
7753             int N = in.readInt();
7754             if (N == -1) {
7755                 return null;
7756             }
7757 
7758             if (N == 0) {
7759                 return new ArrayList<>(0);
7760             }
7761 
7762             String componentName = in.readString();
7763             final ArrayList<T> intentsList;
7764             try {
7765                 final Class<T> cls = (Class<T>) Class.forName(componentName);
7766                 final Constructor<T> cons = cls.getConstructor(Parcel.class);
7767 
7768                 intentsList = new ArrayList<>(N);
7769                 for (int i = 0; i < N; ++i) {
7770                     intentsList.add(cons.newInstance(in));
7771                 }
7772             } catch (ReflectiveOperationException ree) {
7773                 throw new AssertionError("Unable to construct intent list for: " + componentName);
7774             }
7775 
7776             return intentsList;
7777         }
7778 
appendComponentShortName(StringBuilder sb)7779         public void appendComponentShortName(StringBuilder sb) {
7780             ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
7781         }
7782 
printComponentShortName(PrintWriter pw)7783         public void printComponentShortName(PrintWriter pw) {
7784             ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
7785         }
7786 
setPackageName(String packageName)7787         public void setPackageName(String packageName) {
7788             componentName = null;
7789             componentShortName = null;
7790         }
7791     }
7792 
7793     public final static class Permission extends Component<IntentInfo> implements Parcelable {
7794         @UnsupportedAppUsage
7795         public final PermissionInfo info;
7796         @UnsupportedAppUsage
7797         public boolean tree;
7798         @UnsupportedAppUsage
7799         public PermissionGroup group;
7800 
7801         /**
7802          * @hide
7803          */
Permission(Package owner, @Nullable String backgroundPermission)7804         public Permission(Package owner, @Nullable String backgroundPermission) {
7805             super(owner);
7806             info = new PermissionInfo(backgroundPermission);
7807         }
7808 
7809         @UnsupportedAppUsage
Permission(Package _owner, PermissionInfo _info)7810         public Permission(Package _owner, PermissionInfo _info) {
7811             super(_owner);
7812             info = _info;
7813         }
7814 
setPackageName(String packageName)7815         public void setPackageName(String packageName) {
7816             super.setPackageName(packageName);
7817             info.packageName = packageName;
7818         }
7819 
toString()7820         public String toString() {
7821             return "Permission{"
7822                 + Integer.toHexString(System.identityHashCode(this))
7823                 + " " + info.name + "}";
7824         }
7825 
7826         @Override
describeContents()7827         public int describeContents() {
7828             return 0;
7829         }
7830 
7831         @Override
writeToParcel(Parcel dest, int flags)7832         public void writeToParcel(Parcel dest, int flags) {
7833             super.writeToParcel(dest, flags);
7834             dest.writeParcelable(info, flags);
7835             dest.writeInt(tree ? 1 : 0);
7836             dest.writeParcelable(group, flags);
7837         }
7838 
7839         /** @hide */
isAppOp()7840         public boolean isAppOp() {
7841             return info.isAppOp();
7842         }
7843 
Permission(Parcel in)7844         private Permission(Parcel in) {
7845             super(in);
7846             final ClassLoader boot = Object.class.getClassLoader();
7847             info = in.readParcelable(boot, android.content.pm.PermissionInfo.class);
7848             if (info.group != null) {
7849                 info.group = info.group.intern();
7850             }
7851 
7852             tree = (in.readInt() == 1);
7853             group = in.readParcelable(boot, android.content.pm.PackageParser.PermissionGroup.class);
7854         }
7855 
7856         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Permission>() {
7857             public Permission createFromParcel(Parcel in) {
7858                 return new Permission(in);
7859             }
7860 
7861             public Permission[] newArray(int size) {
7862                 return new Permission[size];
7863             }
7864         };
7865     }
7866 
7867     public final static class PermissionGroup extends Component<IntentInfo> implements Parcelable {
7868         @UnsupportedAppUsage
7869         public final PermissionGroupInfo info;
7870 
PermissionGroup(Package owner, @StringRes int requestDetailResourceId, @StringRes int backgroundRequestResourceId, @StringRes int backgroundRequestDetailResourceId)7871         public PermissionGroup(Package owner, @StringRes int requestDetailResourceId,
7872                 @StringRes int backgroundRequestResourceId,
7873                 @StringRes int backgroundRequestDetailResourceId) {
7874             super(owner);
7875             info = new PermissionGroupInfo(requestDetailResourceId, backgroundRequestResourceId,
7876                     backgroundRequestDetailResourceId);
7877         }
7878 
PermissionGroup(Package _owner, PermissionGroupInfo _info)7879         public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
7880             super(_owner);
7881             info = _info;
7882         }
7883 
setPackageName(String packageName)7884         public void setPackageName(String packageName) {
7885             super.setPackageName(packageName);
7886             info.packageName = packageName;
7887         }
7888 
toString()7889         public String toString() {
7890             return "PermissionGroup{"
7891                 + Integer.toHexString(System.identityHashCode(this))
7892                 + " " + info.name + "}";
7893         }
7894 
7895         @Override
describeContents()7896         public int describeContents() {
7897             return 0;
7898         }
7899 
7900         @Override
writeToParcel(Parcel dest, int flags)7901         public void writeToParcel(Parcel dest, int flags) {
7902             super.writeToParcel(dest, flags);
7903             dest.writeParcelable(info, flags);
7904         }
7905 
PermissionGroup(Parcel in)7906         private PermissionGroup(Parcel in) {
7907             super(in);
7908             info = in.readParcelable(Object.class.getClassLoader(), android.content.pm.PermissionGroupInfo.class);
7909         }
7910 
7911         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<PermissionGroup>() {
7912             public PermissionGroup createFromParcel(Parcel in) {
7913                 return new PermissionGroup(in);
7914             }
7915 
7916             public PermissionGroup[] newArray(int size) {
7917                 return new PermissionGroup[size];
7918             }
7919         };
7920     }
7921 
copyNeeded(int flags, Package p, FrameworkPackageUserState state, Bundle metaData, int userId)7922     private static boolean copyNeeded(int flags, Package p,
7923             FrameworkPackageUserState state, Bundle metaData, int userId) {
7924         if (userId != UserHandle.USER_SYSTEM) {
7925             // We always need to copy for other users, since we need
7926             // to fix up the uid.
7927             return true;
7928         }
7929         if (state.getEnabledState() != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
7930             boolean enabled =
7931                     state.getEnabledState() == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
7932             if (p.applicationInfo.enabled != enabled) {
7933                 return true;
7934             }
7935         }
7936         boolean suspended = (p.applicationInfo.flags & FLAG_SUSPENDED) != 0;
7937         if (state.isSuspended() != suspended) {
7938             return true;
7939         }
7940         if (!state.isInstalled() || state.isHidden()) {
7941             return true;
7942         }
7943         if (state.isStopped()) {
7944             return true;
7945         }
7946         if (state.isInstantApp() != p.applicationInfo.isInstantApp()) {
7947             return true;
7948         }
7949         if ((flags & PackageManager.GET_META_DATA) != 0
7950                 && (metaData != null || p.mAppMetaData != null)) {
7951             return true;
7952         }
7953         if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
7954                 && p.usesLibraryFiles != null) {
7955             return true;
7956         }
7957         if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
7958                 && p.usesLibraryInfos != null) {
7959             return true;
7960         }
7961         if (p.staticSharedLibName != null) {
7962             return true;
7963         }
7964         return false;
7965     }
7966 
7967     @UnsupportedAppUsage
generateApplicationInfo(Package p, int flags, FrameworkPackageUserState state)7968     public static ApplicationInfo generateApplicationInfo(Package p, int flags,
7969             FrameworkPackageUserState state) {
7970         return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
7971     }
7972 
updateApplicationInfo(ApplicationInfo ai, int flags, FrameworkPackageUserState state)7973     private static void updateApplicationInfo(ApplicationInfo ai, int flags,
7974             FrameworkPackageUserState state) {
7975         // CompatibilityMode is global state.
7976         if (!sCompatibilityModeEnabled) {
7977             ai.disableCompatibilityMode();
7978         }
7979         if (state.isInstalled()) {
7980             ai.flags |= ApplicationInfo.FLAG_INSTALLED;
7981         } else {
7982             ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
7983         }
7984         if (state.isSuspended()) {
7985             ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
7986         } else {
7987             ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
7988         }
7989         if (state.isInstantApp()) {
7990             ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT;
7991         } else {
7992             ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT;
7993         }
7994         if (state.isVirtualPreload()) {
7995             ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7996         } else {
7997             ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7998         }
7999         if (state.isHidden()) {
8000             ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
8001         } else {
8002             ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
8003         }
8004         if (state.getEnabledState() == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
8005             ai.enabled = true;
8006         } else if (state.getEnabledState()
8007                 == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
8008             ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
8009         } else if (state.getEnabledState() == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
8010                 || state.getEnabledState()
8011                 == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
8012             ai.enabled = false;
8013         }
8014         ai.enabledSetting = state.getEnabledState();
8015         if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
8016             ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
8017         }
8018         ai.seInfoUser = getSeinfoUser(state);
8019         final OverlayPaths overlayPaths = state.getAllOverlayPaths();
8020         if (overlayPaths != null) {
8021             ai.resourceDirs = overlayPaths.getResourceDirs().toArray(new String[0]);
8022             ai.overlayPaths = overlayPaths.getOverlayPaths().toArray(new String[0]);
8023         }
8024         ai.icon = (sUseRoundIcon && ai.roundIconRes != 0) ? ai.roundIconRes : ai.iconRes;
8025     }
8026 
8027     @UnsupportedAppUsage
generateApplicationInfo(Package p, int flags, FrameworkPackageUserState state, int userId)8028     public static ApplicationInfo generateApplicationInfo(Package p, int flags,
8029             FrameworkPackageUserState state, int userId) {
8030         if (p == null) return null;
8031         if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
8032             return null;
8033         }
8034         if (!copyNeeded(flags, p, state, null, userId)
8035                 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
8036                         || state.getEnabledState()
8037                                 != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
8038             // In this case it is safe to directly modify the internal ApplicationInfo state:
8039             // - CompatibilityMode is global state, so will be the same for every call.
8040             // - We only come in to here if the app should reported as installed; this is the
8041             // default state, and we will do a copy otherwise.
8042             // - The enable state will always be reported the same for the application across
8043             // calls; the only exception is for the UNTIL_USED mode, and in that case we will
8044             // be doing a copy.
8045             updateApplicationInfo(p.applicationInfo, flags, state);
8046             return p.applicationInfo;
8047         }
8048 
8049         // Make shallow copy so we can store the metadata/libraries safely
8050         ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
8051         ai.initForUser(userId);
8052         if ((flags & PackageManager.GET_META_DATA) != 0) {
8053             ai.metaData = p.mAppMetaData;
8054         }
8055         if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
8056             ai.sharedLibraryFiles = p.usesLibraryFiles;
8057             ai.sharedLibraryInfos = p.usesLibraryInfos;
8058         }
8059         if (state.isStopped()) {
8060             ai.flags |= ApplicationInfo.FLAG_STOPPED;
8061         } else {
8062             ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
8063         }
8064         updateApplicationInfo(ai, flags, state);
8065         return ai;
8066     }
8067 
generateApplicationInfo(ApplicationInfo ai, int flags, FrameworkPackageUserState state, int userId)8068     public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
8069             FrameworkPackageUserState state, int userId) {
8070         if (ai == null) return null;
8071         if (!checkUseInstalledOrHidden(flags, state, ai)) {
8072             return null;
8073         }
8074         // This is only used to return the ResolverActivity; we will just always
8075         // make a copy.
8076         ai = new ApplicationInfo(ai);
8077         ai.initForUser(userId);
8078         if (state.isStopped()) {
8079             ai.flags |= ApplicationInfo.FLAG_STOPPED;
8080         } else {
8081             ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
8082         }
8083         updateApplicationInfo(ai, flags, state);
8084         return ai;
8085     }
8086 
8087     @UnsupportedAppUsage
generatePermissionInfo( Permission p, int flags)8088     public static final PermissionInfo generatePermissionInfo(
8089             Permission p, int flags) {
8090         if (p == null) return null;
8091         if ((flags&PackageManager.GET_META_DATA) == 0) {
8092             return p.info;
8093         }
8094         PermissionInfo pi = new PermissionInfo(p.info);
8095         pi.metaData = p.metaData;
8096         return pi;
8097     }
8098 
8099     @UnsupportedAppUsage
generatePermissionGroupInfo( PermissionGroup pg, int flags)8100     public static final PermissionGroupInfo generatePermissionGroupInfo(
8101             PermissionGroup pg, int flags) {
8102         if (pg == null) return null;
8103         if ((flags&PackageManager.GET_META_DATA) == 0) {
8104             return pg.info;
8105         }
8106         PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
8107         pgi.metaData = pg.metaData;
8108         return pgi;
8109     }
8110 
8111     public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable {
8112         @UnsupportedAppUsage
8113         public final ActivityInfo info;
8114         private boolean mHasMaxAspectRatio;
8115         private boolean mHasMinAspectRatio;
8116 
hasMaxAspectRatio()8117         private boolean hasMaxAspectRatio() {
8118             return mHasMaxAspectRatio;
8119         }
8120 
hasMinAspectRatio()8121         private boolean hasMinAspectRatio() {
8122             return mHasMinAspectRatio;
8123         }
8124 
8125         // To construct custom activity which does not exist in manifest
Activity(final Package owner, final String className, final ActivityInfo info)8126         Activity(final Package owner, final String className, final ActivityInfo info) {
8127             super(owner, new ArrayList<>(0), className);
8128             this.info = info;
8129             this.info.applicationInfo = owner.applicationInfo;
8130         }
8131 
Activity(final ParseComponentArgs args, final ActivityInfo _info)8132         public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
8133             super(args, _info);
8134             info = _info;
8135             info.applicationInfo = args.owner.applicationInfo;
8136         }
8137 
setPackageName(String packageName)8138         public void setPackageName(String packageName) {
8139             super.setPackageName(packageName);
8140             info.packageName = packageName;
8141         }
8142 
8143 
setMaxAspectRatio(float maxAspectRatio)8144         private void setMaxAspectRatio(float maxAspectRatio) {
8145             if (info.resizeMode == RESIZE_MODE_RESIZEABLE
8146                     || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
8147                 // Resizeable activities can be put in any aspect ratio.
8148                 return;
8149             }
8150 
8151             if (maxAspectRatio < 1.0f && maxAspectRatio != 0) {
8152                 // Ignore any value lesser than 1.0.
8153                 return;
8154             }
8155 
8156             info.setMaxAspectRatio(maxAspectRatio);
8157             mHasMaxAspectRatio = true;
8158         }
8159 
setMinAspectRatio(float minAspectRatio)8160         private void setMinAspectRatio(float minAspectRatio) {
8161             if (info.resizeMode == RESIZE_MODE_RESIZEABLE
8162                     || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
8163                 // Resizeable activities can be put in any aspect ratio.
8164                 return;
8165             }
8166 
8167             if (minAspectRatio < 1.0f && minAspectRatio != 0) {
8168                 // Ignore any value lesser than 1.0.
8169                 return;
8170             }
8171 
8172             info.setMinAspectRatio(minAspectRatio);
8173             mHasMinAspectRatio = true;
8174         }
8175 
toString()8176         public String toString() {
8177             StringBuilder sb = new StringBuilder(128);
8178             sb.append("Activity{");
8179             sb.append(Integer.toHexString(System.identityHashCode(this)));
8180             sb.append(' ');
8181             appendComponentShortName(sb);
8182             sb.append('}');
8183             return sb.toString();
8184         }
8185 
8186         @Override
describeContents()8187         public int describeContents() {
8188             return 0;
8189         }
8190 
8191         @Override
writeToParcel(Parcel dest, int flags)8192         public void writeToParcel(Parcel dest, int flags) {
8193             super.writeToParcel(dest, flags);
8194             dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
8195             dest.writeBoolean(mHasMaxAspectRatio);
8196             dest.writeBoolean(mHasMinAspectRatio);
8197         }
8198 
Activity(Parcel in)8199         private Activity(Parcel in) {
8200             super(in);
8201             info = in.readParcelable(Object.class.getClassLoader(), android.content.pm.ActivityInfo.class);
8202             mHasMaxAspectRatio = in.readBoolean();
8203             mHasMinAspectRatio = in.readBoolean();
8204 
8205             for (ActivityIntentInfo aii : intents) {
8206                 aii.activity = this;
8207                 order = Math.max(aii.getOrder(), order);
8208             }
8209 
8210             if (info.permission != null) {
8211                 info.permission = info.permission.intern();
8212             }
8213         }
8214 
8215         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Activity>() {
8216             public Activity createFromParcel(Parcel in) {
8217                 return new Activity(in);
8218             }
8219 
8220             public Activity[] newArray(int size) {
8221                 return new Activity[size];
8222             }
8223         };
8224     }
8225 
8226     @UnsupportedAppUsage
generateActivityInfo(Activity a, int flags, FrameworkPackageUserState state, int userId)8227     public static final ActivityInfo generateActivityInfo(Activity a, int flags,
8228             FrameworkPackageUserState state, int userId) {
8229         return generateActivityInfo(a, flags, state, userId, null);
8230     }
8231 
generateActivityInfo(Activity a, int flags, FrameworkPackageUserState state, int userId, ApplicationInfo applicationInfo)8232     private static ActivityInfo generateActivityInfo(Activity a, int flags,
8233             FrameworkPackageUserState state, int userId, ApplicationInfo applicationInfo) {
8234         if (a == null) return null;
8235         if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
8236             return null;
8237         }
8238         if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
8239             updateApplicationInfo(a.info.applicationInfo, flags, state);
8240             return a.info;
8241         }
8242         // Make shallow copies so we can store the metadata safely
8243         ActivityInfo ai = new ActivityInfo(a.info);
8244         ai.metaData = a.metaData;
8245 
8246         if (applicationInfo == null) {
8247             applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
8248         }
8249         ai.applicationInfo = applicationInfo;
8250 
8251         return ai;
8252     }
8253 
generateActivityInfo(ActivityInfo ai, int flags, FrameworkPackageUserState state, int userId)8254     public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
8255             FrameworkPackageUserState state, int userId) {
8256         if (ai == null) return null;
8257         if (!checkUseInstalledOrHidden(flags, state, ai.applicationInfo)) {
8258             return null;
8259         }
8260         // This is only used to return the ResolverActivity; we will just always
8261         // make a copy.
8262         ai = new ActivityInfo(ai);
8263         ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
8264         return ai;
8265     }
8266 
8267     public final static class Service extends Component<ServiceIntentInfo> implements Parcelable {
8268         @UnsupportedAppUsage
8269         public final ServiceInfo info;
8270 
Service(final ParseComponentArgs args, final ServiceInfo _info)8271         public Service(final ParseComponentArgs args, final ServiceInfo _info) {
8272             super(args, _info);
8273             info = _info;
8274             info.applicationInfo = args.owner.applicationInfo;
8275         }
8276 
setPackageName(String packageName)8277         public void setPackageName(String packageName) {
8278             super.setPackageName(packageName);
8279             info.packageName = packageName;
8280         }
8281 
toString()8282         public String toString() {
8283             StringBuilder sb = new StringBuilder(128);
8284             sb.append("Service{");
8285             sb.append(Integer.toHexString(System.identityHashCode(this)));
8286             sb.append(' ');
8287             appendComponentShortName(sb);
8288             sb.append('}');
8289             return sb.toString();
8290         }
8291 
8292         @Override
describeContents()8293         public int describeContents() {
8294             return 0;
8295         }
8296 
8297         @Override
writeToParcel(Parcel dest, int flags)8298         public void writeToParcel(Parcel dest, int flags) {
8299             super.writeToParcel(dest, flags);
8300             dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
8301         }
8302 
Service(Parcel in)8303         private Service(Parcel in) {
8304             super(in);
8305             info = in.readParcelable(Object.class.getClassLoader(), android.content.pm.ServiceInfo.class);
8306 
8307             for (ServiceIntentInfo aii : intents) {
8308                 aii.service = this;
8309                 order = Math.max(aii.getOrder(), order);
8310             }
8311 
8312             if (info.permission != null) {
8313                 info.permission = info.permission.intern();
8314             }
8315         }
8316 
8317         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Service>() {
8318             public Service createFromParcel(Parcel in) {
8319                 return new Service(in);
8320             }
8321 
8322             public Service[] newArray(int size) {
8323                 return new Service[size];
8324             }
8325         };
8326     }
8327 
8328     @UnsupportedAppUsage
generateServiceInfo(Service s, int flags, FrameworkPackageUserState state, int userId)8329     public static final ServiceInfo generateServiceInfo(Service s, int flags,
8330             FrameworkPackageUserState state, int userId) {
8331         return generateServiceInfo(s, flags, state, userId, null);
8332     }
8333 
generateServiceInfo(Service s, int flags, FrameworkPackageUserState state, int userId, ApplicationInfo applicationInfo)8334     private static ServiceInfo generateServiceInfo(Service s, int flags,
8335             FrameworkPackageUserState state, int userId, ApplicationInfo applicationInfo) {
8336         if (s == null) return null;
8337         if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) {
8338             return null;
8339         }
8340         if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
8341             updateApplicationInfo(s.info.applicationInfo, flags, state);
8342             return s.info;
8343         }
8344         // Make shallow copies so we can store the metadata safely
8345         ServiceInfo si = new ServiceInfo(s.info);
8346         si.metaData = s.metaData;
8347 
8348         if (applicationInfo == null) {
8349             applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
8350         }
8351         si.applicationInfo = applicationInfo;
8352 
8353         return si;
8354     }
8355 
8356     public final static class Provider extends Component<ProviderIntentInfo> implements Parcelable {
8357         @UnsupportedAppUsage
8358         public final ProviderInfo info;
8359         @UnsupportedAppUsage
8360         public boolean syncable;
8361 
Provider(final ParseComponentArgs args, final ProviderInfo _info)8362         public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
8363             super(args, _info);
8364             info = _info;
8365             info.applicationInfo = args.owner.applicationInfo;
8366             syncable = false;
8367         }
8368 
8369         @UnsupportedAppUsage
Provider(Provider existingProvider)8370         public Provider(Provider existingProvider) {
8371             super(existingProvider);
8372             this.info = existingProvider.info;
8373             this.syncable = existingProvider.syncable;
8374         }
8375 
setPackageName(String packageName)8376         public void setPackageName(String packageName) {
8377             super.setPackageName(packageName);
8378             info.packageName = packageName;
8379         }
8380 
toString()8381         public String toString() {
8382             StringBuilder sb = new StringBuilder(128);
8383             sb.append("Provider{");
8384             sb.append(Integer.toHexString(System.identityHashCode(this)));
8385             sb.append(' ');
8386             appendComponentShortName(sb);
8387             sb.append('}');
8388             return sb.toString();
8389         }
8390 
8391         @Override
describeContents()8392         public int describeContents() {
8393             return 0;
8394         }
8395 
8396         @Override
writeToParcel(Parcel dest, int flags)8397         public void writeToParcel(Parcel dest, int flags) {
8398             super.writeToParcel(dest, flags);
8399             dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
8400             dest.writeInt((syncable) ? 1 : 0);
8401         }
8402 
Provider(Parcel in)8403         private Provider(Parcel in) {
8404             super(in);
8405             info = in.readParcelable(Object.class.getClassLoader(), android.content.pm.ProviderInfo.class);
8406             syncable = (in.readInt() == 1);
8407 
8408             for (ProviderIntentInfo aii : intents) {
8409                 aii.provider = this;
8410             }
8411 
8412             if (info.readPermission != null) {
8413                 info.readPermission = info.readPermission.intern();
8414             }
8415 
8416             if (info.writePermission != null) {
8417                 info.writePermission = info.writePermission.intern();
8418             }
8419 
8420             if (info.authority != null) {
8421                 info.authority = info.authority.intern();
8422             }
8423         }
8424 
8425         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Provider>() {
8426             public Provider createFromParcel(Parcel in) {
8427                 return new Provider(in);
8428             }
8429 
8430             public Provider[] newArray(int size) {
8431                 return new Provider[size];
8432             }
8433         };
8434     }
8435 
8436     @UnsupportedAppUsage
generateProviderInfo(Provider p, int flags, FrameworkPackageUserState state, int userId)8437     public static final ProviderInfo generateProviderInfo(Provider p, int flags,
8438             FrameworkPackageUserState state, int userId) {
8439         return generateProviderInfo(p, flags, state, userId, null);
8440     }
8441 
generateProviderInfo(Provider p, int flags, FrameworkPackageUserState state, int userId, ApplicationInfo applicationInfo)8442     private static ProviderInfo generateProviderInfo(Provider p, int flags,
8443             FrameworkPackageUserState state, int userId, ApplicationInfo applicationInfo) {
8444         if (p == null) return null;
8445         if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) {
8446             return null;
8447         }
8448         if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
8449                 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
8450                 || p.info.uriPermissionPatterns == null)) {
8451             updateApplicationInfo(p.info.applicationInfo, flags, state);
8452             return p.info;
8453         }
8454         // Make shallow copies so we can store the metadata safely
8455         ProviderInfo pi = new ProviderInfo(p.info);
8456         pi.metaData = p.metaData;
8457         if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
8458             pi.uriPermissionPatterns = null;
8459         }
8460 
8461         if (applicationInfo == null) {
8462             applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
8463         }
8464         pi.applicationInfo = applicationInfo;
8465 
8466         return pi;
8467     }
8468 
8469     public final static class Instrumentation extends Component<IntentInfo> implements
8470             Parcelable {
8471         @UnsupportedAppUsage
8472         public final InstrumentationInfo info;
8473 
Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info)8474         public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
8475             super(args, _info);
8476             info = _info;
8477         }
8478 
setPackageName(String packageName)8479         public void setPackageName(String packageName) {
8480             super.setPackageName(packageName);
8481             info.packageName = packageName;
8482         }
8483 
toString()8484         public String toString() {
8485             StringBuilder sb = new StringBuilder(128);
8486             sb.append("Instrumentation{");
8487             sb.append(Integer.toHexString(System.identityHashCode(this)));
8488             sb.append(' ');
8489             appendComponentShortName(sb);
8490             sb.append('}');
8491             return sb.toString();
8492         }
8493 
8494         @Override
describeContents()8495         public int describeContents() {
8496             return 0;
8497         }
8498 
8499         @Override
writeToParcel(Parcel dest, int flags)8500         public void writeToParcel(Parcel dest, int flags) {
8501             super.writeToParcel(dest, flags);
8502             dest.writeParcelable(info, flags);
8503         }
8504 
Instrumentation(Parcel in)8505         private Instrumentation(Parcel in) {
8506             super(in);
8507             info = in.readParcelable(Object.class.getClassLoader(), android.content.pm.InstrumentationInfo.class);
8508 
8509             if (info.targetPackage != null) {
8510                 info.targetPackage = info.targetPackage.intern();
8511             }
8512 
8513             if (info.targetProcesses != null) {
8514                 info.targetProcesses = info.targetProcesses.intern();
8515             }
8516         }
8517 
8518         public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Instrumentation>() {
8519             public Instrumentation createFromParcel(Parcel in) {
8520                 return new Instrumentation(in);
8521             }
8522 
8523             public Instrumentation[] newArray(int size) {
8524                 return new Instrumentation[size];
8525             }
8526         };
8527     }
8528 
8529     @UnsupportedAppUsage
generateInstrumentationInfo( Instrumentation i, int flags)8530     public static final InstrumentationInfo generateInstrumentationInfo(
8531             Instrumentation i, int flags) {
8532         if (i == null) return null;
8533         if ((flags&PackageManager.GET_META_DATA) == 0) {
8534             return i.info;
8535         }
8536         InstrumentationInfo ii = new InstrumentationInfo(i.info);
8537         ii.metaData = i.metaData;
8538         return ii;
8539     }
8540 
8541     public static abstract class IntentInfo extends IntentFilter {
8542         @UnsupportedAppUsage
8543         public boolean hasDefault;
8544         @UnsupportedAppUsage
8545         public int labelRes;
8546         @UnsupportedAppUsage
8547         public CharSequence nonLocalizedLabel;
8548         @UnsupportedAppUsage
8549         public int icon;
8550         @UnsupportedAppUsage
8551         public int logo;
8552         @UnsupportedAppUsage
8553         public int banner;
8554         public int preferred;
8555 
8556         @UnsupportedAppUsage
IntentInfo()8557         protected IntentInfo() {
8558         }
8559 
IntentInfo(Parcel dest)8560         protected IntentInfo(Parcel dest) {
8561             super(dest);
8562             hasDefault = (dest.readInt() == 1);
8563             labelRes = dest.readInt();
8564             nonLocalizedLabel = dest.readCharSequence();
8565             icon = dest.readInt();
8566             logo = dest.readInt();
8567             banner = dest.readInt();
8568             preferred = dest.readInt();
8569         }
8570 
8571 
writeIntentInfoToParcel(Parcel dest, int flags)8572         public void writeIntentInfoToParcel(Parcel dest, int flags) {
8573             super.writeToParcel(dest, flags);
8574             dest.writeInt(hasDefault ? 1 : 0);
8575             dest.writeInt(labelRes);
8576             dest.writeCharSequence(nonLocalizedLabel);
8577             dest.writeInt(icon);
8578             dest.writeInt(logo);
8579             dest.writeInt(banner);
8580             dest.writeInt(preferred);
8581         }
8582     }
8583 
8584     public final static class ActivityIntentInfo extends IntentInfo {
8585         @UnsupportedAppUsage
8586         public Activity activity;
8587 
ActivityIntentInfo(Activity _activity)8588         public ActivityIntentInfo(Activity _activity) {
8589             activity = _activity;
8590         }
8591 
toString()8592         public String toString() {
8593             StringBuilder sb = new StringBuilder(128);
8594             sb.append("ActivityIntentInfo{");
8595             sb.append(Integer.toHexString(System.identityHashCode(this)));
8596             sb.append(' ');
8597             activity.appendComponentShortName(sb);
8598             sb.append('}');
8599             return sb.toString();
8600         }
8601 
ActivityIntentInfo(Parcel in)8602         public ActivityIntentInfo(Parcel in) {
8603             super(in);
8604         }
8605     }
8606 
8607     public final static class ServiceIntentInfo extends IntentInfo {
8608         @UnsupportedAppUsage
8609         public Service service;
8610 
ServiceIntentInfo(Service _service)8611         public ServiceIntentInfo(Service _service) {
8612             service = _service;
8613         }
8614 
toString()8615         public String toString() {
8616             StringBuilder sb = new StringBuilder(128);
8617             sb.append("ServiceIntentInfo{");
8618             sb.append(Integer.toHexString(System.identityHashCode(this)));
8619             sb.append(' ');
8620             service.appendComponentShortName(sb);
8621             sb.append('}');
8622             return sb.toString();
8623         }
8624 
ServiceIntentInfo(Parcel in)8625         public ServiceIntentInfo(Parcel in) {
8626             super(in);
8627         }
8628     }
8629 
8630     public static final class ProviderIntentInfo extends IntentInfo {
8631         @UnsupportedAppUsage
8632         public Provider provider;
8633 
ProviderIntentInfo(Provider provider)8634         public ProviderIntentInfo(Provider provider) {
8635             this.provider = provider;
8636         }
8637 
toString()8638         public String toString() {
8639             StringBuilder sb = new StringBuilder(128);
8640             sb.append("ProviderIntentInfo{");
8641             sb.append(Integer.toHexString(System.identityHashCode(this)));
8642             sb.append(' ');
8643             provider.appendComponentShortName(sb);
8644             sb.append('}');
8645             return sb.toString();
8646         }
8647 
ProviderIntentInfo(Parcel in)8648         public ProviderIntentInfo(Parcel in) {
8649             super(in);
8650         }
8651     }
8652 
8653     /**
8654      * @hide
8655      */
8656     @UnsupportedAppUsage
setCompatibilityModeEnabled(boolean compatibilityModeEnabled)8657     public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
8658         sCompatibilityModeEnabled = compatibilityModeEnabled;
8659     }
8660 
8661     /**
8662      * @hide
8663      */
readConfigUseRoundIcon(Resources r)8664     public static void readConfigUseRoundIcon(Resources r) {
8665         if (r != null) {
8666             sUseRoundIcon = r.getBoolean(com.android.internal.R.bool.config_useRoundIcon);
8667             return;
8668         }
8669 
8670         ApplicationInfo androidAppInfo;
8671         try {
8672             androidAppInfo = ActivityThread.getPackageManager().getApplicationInfo(
8673                     "android", 0 /* flags */,
8674                 UserHandle.myUserId());
8675         } catch (RemoteException e) {
8676             throw e.rethrowFromSystemServer();
8677         }
8678         Resources systemResources = Resources.getSystem();
8679 
8680         // Create in-flight as this overlayable resource is only used when config changes
8681         Resources overlayableRes = ResourcesManager.getInstance().getResources(null,
8682                 null,
8683                 null,
8684                 androidAppInfo.resourceDirs,
8685                 androidAppInfo.overlayPaths,
8686                 androidAppInfo.sharedLibraryFiles,
8687                 null,
8688                 null,
8689                 systemResources.getCompatibilityInfo(),
8690                 systemResources.getClassLoader(),
8691                 null);
8692 
8693         sUseRoundIcon = overlayableRes.getBoolean(com.android.internal.R.bool.config_useRoundIcon);
8694     }
8695 
8696     public static class PackageParserException extends Exception {
8697         public final int error;
8698 
PackageParserException(int error, String detailMessage)8699         public PackageParserException(int error, String detailMessage) {
8700             super(detailMessage);
8701             this.error = error;
8702         }
8703 
PackageParserException(int error, String detailMessage, Throwable throwable)8704         public PackageParserException(int error, String detailMessage, Throwable throwable) {
8705             super(detailMessage, throwable);
8706             this.error = error;
8707         }
8708     }
8709 
8710     // Duplicate the SplitAsset related classes with PackageParser.Package/ApkLite here, and
8711     // change the original one using new Package/ApkLite. The propose is that we don't want to
8712     // have two branches of methods in SplitAsset related classes so we can keep real classes
8713     // clean and move all the legacy code to one place.
8714 
8715     /**
8716      * Simple interface for loading base Assets and Splits. Used by PackageParser when parsing
8717      * split APKs.
8718      *
8719      * @hide
8720      * @deprecated Do not use. New changes should use
8721      * {@link android.content.pm.split.SplitAssetLoader} instead.
8722      */
8723     @Deprecated
8724     private interface SplitAssetLoader extends AutoCloseable {
getBaseAssetManager()8725         AssetManager getBaseAssetManager() throws PackageParserException;
getSplitAssetManager(int splitIdx)8726         AssetManager getSplitAssetManager(int splitIdx) throws PackageParserException;
8727 
getBaseApkAssets()8728         ApkAssets getBaseApkAssets();
8729     }
8730 
8731     /**
8732      * A helper class that implements the dependency tree traversal for splits. Callbacks
8733      * are implemented by subclasses to notify whether a split has already been constructed
8734      * and is cached, and to actually create the split requested.
8735      *
8736      * This helper is meant to be subclassed so as to reduce the number of allocations
8737      * needed to make use of it.
8738      *
8739      * All inputs and outputs are assumed to be indices into an array of splits.
8740      *
8741      * @hide
8742      * @deprecated Do not use. New changes should use
8743      * {@link android.content.pm.split.SplitDependencyLoader} instead.
8744      */
8745     @Deprecated
8746     private abstract static class SplitDependencyLoader<E extends Exception> {
8747         private final @NonNull SparseArray<int[]> mDependencies;
8748 
8749         /**
8750          * Construct a new SplitDependencyLoader. Meant to be called from the
8751          * subclass constructor.
8752          * @param dependencies The dependency tree of splits.
8753          */
SplitDependencyLoader(@onNull SparseArray<int[]> dependencies)8754         protected SplitDependencyLoader(@NonNull SparseArray<int[]> dependencies) {
8755             mDependencies = dependencies;
8756         }
8757 
8758         /**
8759          * Traverses the dependency tree and constructs any splits that are not already
8760          * cached. This routine short-circuits and skips the creation of splits closer to the
8761          * root if they are cached, as reported by the subclass implementation of
8762          * {@link #isSplitCached(int)}. The construction of splits is delegated to the subclass
8763          * implementation of {@link #constructSplit(int, int[], int)}.
8764          * @param splitIdx The index of the split to load. 0 represents the base Application.
8765          */
loadDependenciesForSplit(@ntRangefrom = 0) int splitIdx)8766         protected void loadDependenciesForSplit(@IntRange(from = 0) int splitIdx) throws E {
8767             // Quick check before any allocations are done.
8768             if (isSplitCached(splitIdx)) {
8769                 return;
8770             }
8771 
8772             // Special case the base, since it has no dependencies.
8773             if (splitIdx == 0) {
8774                 final int[] configSplitIndices = collectConfigSplitIndices(0);
8775                 constructSplit(0, configSplitIndices, -1);
8776                 return;
8777             }
8778 
8779             // Build up the dependency hierarchy.
8780             final IntArray linearDependencies = new IntArray();
8781             linearDependencies.add(splitIdx);
8782 
8783             // Collect all the dependencies that need to be constructed.
8784             // They will be listed from leaf to root.
8785             while (true) {
8786                 // Only follow the first index into the array. The others are config splits and
8787                 // get loaded with the split.
8788                 final int[] deps = mDependencies.get(splitIdx);
8789                 if (deps != null && deps.length > 0) {
8790                     splitIdx = deps[0];
8791                 } else {
8792                     splitIdx = -1;
8793                 }
8794 
8795                 if (splitIdx < 0 || isSplitCached(splitIdx)) {
8796                     break;
8797                 }
8798 
8799                 linearDependencies.add(splitIdx);
8800             }
8801 
8802             // Visit each index, from right to left (root to leaf).
8803             int parentIdx = splitIdx;
8804             for (int i = linearDependencies.size() - 1; i >= 0; i--) {
8805                 final int idx = linearDependencies.get(i);
8806                 final int[] configSplitIndices = collectConfigSplitIndices(idx);
8807                 constructSplit(idx, configSplitIndices, parentIdx);
8808                 parentIdx = idx;
8809             }
8810         }
8811 
collectConfigSplitIndices(int splitIdx)8812         private @NonNull int[] collectConfigSplitIndices(int splitIdx) {
8813             // The config splits appear after the first element.
8814             final int[] deps = mDependencies.get(splitIdx);
8815             if (deps == null || deps.length <= 1) {
8816                 return EmptyArray.INT;
8817             }
8818             return Arrays.copyOfRange(deps, 1, deps.length);
8819         }
8820 
8821         /**
8822          * Subclass to report whether the split at `splitIdx` is cached and need not be constructed.
8823          * It is assumed that if `splitIdx` is cached, any parent of `splitIdx` is also cached.
8824          * @param splitIdx The index of the split to check for in the cache.
8825          * @return true if the split is cached and does not need to be constructed.
8826          */
isSplitCached(@ntRangefrom = 0) int splitIdx)8827         protected abstract boolean isSplitCached(@IntRange(from = 0) int splitIdx);
8828 
8829         /**
8830          * Subclass to construct a split at index `splitIdx` with parent split `parentSplitIdx`.
8831          * The result is expected to be cached by the subclass in its own structures.
8832          * @param splitIdx The index of the split to construct. 0 represents the base Application.
8833          * @param configSplitIndices The array of configuration splits to load along with this
8834          *                           split. May be empty (length == 0) but never null.
8835          * @param parentSplitIdx The index of the parent split. -1 if there is no parent.
8836          * @throws E Subclass defined exception representing failure to construct a split.
8837          */
constructSplit(@ntRangefrom = 0) int splitIdx, @NonNull @IntRange(from = 1) int[] configSplitIndices, @IntRange(from = -1) int parentSplitIdx)8838         protected abstract void constructSplit(@IntRange(from = 0) int splitIdx,
8839                 @NonNull @IntRange(from = 1) int[] configSplitIndices,
8840                 @IntRange(from = -1) int parentSplitIdx) throws E;
8841 
8842         public static class IllegalDependencyException extends Exception {
IllegalDependencyException(String message)8843             private IllegalDependencyException(String message) {
8844                 super(message);
8845             }
8846         }
8847 
append(int[] src, int elem)8848         private static int[] append(int[] src, int elem) {
8849             if (src == null) {
8850                 return new int[] { elem };
8851             }
8852             int[] dst = Arrays.copyOf(src, src.length + 1);
8853             dst[src.length] = elem;
8854             return dst;
8855         }
8856 
createDependenciesFromPackage( PackageLite pkg)8857         public static @NonNull SparseArray<int[]> createDependenciesFromPackage(
8858                 PackageLite pkg)
8859                 throws SplitDependencyLoader.IllegalDependencyException {
8860             // The data structure that holds the dependencies. In PackageParser, splits are stored
8861             // in their own array, separate from the base. We treat all paths as equals, so
8862             // we need to insert the base as index 0, and shift all other splits.
8863             final SparseArray<int[]> splitDependencies = new SparseArray<>();
8864 
8865             // The base depends on nothing.
8866             splitDependencies.put(0, new int[] {-1});
8867 
8868             // First write out the <uses-split> dependencies. These must appear first in the
8869             // array of ints, as is convention in this class.
8870             for (int splitIdx = 0; splitIdx < pkg.splitNames.length; splitIdx++) {
8871                 if (!pkg.isFeatureSplits[splitIdx]) {
8872                     // Non-feature splits don't have dependencies.
8873                     continue;
8874                 }
8875 
8876                 // Implicit dependency on the base.
8877                 final int targetIdx;
8878                 final String splitDependency = pkg.usesSplitNames[splitIdx];
8879                 if (splitDependency != null) {
8880                     final int depIdx = Arrays.binarySearch(pkg.splitNames, splitDependency);
8881                     if (depIdx < 0) {
8882                         throw new SplitDependencyLoader.IllegalDependencyException(
8883                                 "Split '" + pkg.splitNames[splitIdx] + "' requires split '"
8884                                         + splitDependency + "', which is missing.");
8885                     }
8886                     targetIdx = depIdx + 1;
8887                 } else {
8888                     // Implicitly depend on the base.
8889                     targetIdx = 0;
8890                 }
8891                 splitDependencies.put(splitIdx + 1, new int[] {targetIdx});
8892             }
8893 
8894             // Write out the configForSplit reverse-dependencies. These appear after the
8895             // <uses-split> dependencies and are considered leaves.
8896             //
8897             // At this point, all splits in splitDependencies have the first element in their
8898             // array set.
8899             for (int splitIdx = 0, size = pkg.splitNames.length; splitIdx < size; splitIdx++) {
8900                 if (pkg.isFeatureSplits[splitIdx]) {
8901                     // Feature splits are not configForSplits.
8902                     continue;
8903                 }
8904 
8905                 // Implicit feature for the base.
8906                 final int targetSplitIdx;
8907                 final String configForSplit = pkg.configForSplit[splitIdx];
8908                 if (configForSplit != null) {
8909                     final int depIdx = Arrays.binarySearch(pkg.splitNames, configForSplit);
8910                     if (depIdx < 0) {
8911                         throw new SplitDependencyLoader.IllegalDependencyException(
8912                                 "Split '" + pkg.splitNames[splitIdx] + "' targets split '"
8913                                         + configForSplit + "', which is missing.");
8914                     }
8915 
8916                     if (!pkg.isFeatureSplits[depIdx]) {
8917                         throw new SplitDependencyLoader.IllegalDependencyException(
8918                                 "Split '" + pkg.splitNames[splitIdx] + "' declares itself as "
8919                                         + "configuration split for a non-feature split '"
8920                                         + pkg.splitNames[depIdx] + "'");
8921                     }
8922                     targetSplitIdx = depIdx + 1;
8923                 } else {
8924                     targetSplitIdx = 0;
8925                 }
8926                 splitDependencies.put(targetSplitIdx,
8927                         append(splitDependencies.get(targetSplitIdx), splitIdx + 1));
8928             }
8929 
8930             // Verify that there are no cycles.
8931             final BitSet bitset = new BitSet();
8932             for (int i = 0, size = splitDependencies.size(); i < size; i++) {
8933                 int splitIdx = splitDependencies.keyAt(i);
8934 
8935                 bitset.clear();
8936                 while (splitIdx != -1) {
8937                     // Check if this split has been visited yet.
8938                     if (bitset.get(splitIdx)) {
8939                         throw new SplitDependencyLoader.IllegalDependencyException(
8940                                 "Cycle detected in split dependencies.");
8941                     }
8942 
8943                     // Mark the split so that if we visit it again, we no there is a cycle.
8944                     bitset.set(splitIdx);
8945 
8946                     // Follow the first dependency only, the others are leaves by definition.
8947                     final int[] deps = splitDependencies.get(splitIdx);
8948                     splitIdx = deps != null ? deps[0] : -1;
8949                 }
8950             }
8951             return splitDependencies;
8952         }
8953     }
8954 
8955     /**
8956      * Loads the base and split APKs into a single AssetManager.
8957      * @hide
8958      * @deprecated Do not use. New changes should use
8959      * {@link android.content.pm.split.DefaultSplitAssetLoader} instead.
8960      */
8961     @Deprecated
8962     private static class DefaultSplitAssetLoader implements SplitAssetLoader {
8963         private final String mBaseCodePath;
8964         private final String[] mSplitCodePaths;
8965         private final @ParseFlags int mFlags;
8966         private AssetManager mCachedAssetManager;
8967 
8968         private ApkAssets mBaseApkAssets;
8969 
DefaultSplitAssetLoader(PackageLite pkg, @ParseFlags int flags)8970         DefaultSplitAssetLoader(PackageLite pkg, @ParseFlags int flags) {
8971             mBaseCodePath = pkg.baseCodePath;
8972             mSplitCodePaths = pkg.splitCodePaths;
8973             mFlags = flags;
8974         }
8975 
loadApkAssets(String path, @ParseFlags int flags)8976         private static ApkAssets loadApkAssets(String path, @ParseFlags int flags)
8977                 throws PackageParserException {
8978             if ((flags & PackageParser.PARSE_MUST_BE_APK) != 0 && !PackageParser.isApkPath(path)) {
8979                 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
8980                         "Invalid package file: " + path);
8981             }
8982 
8983             try {
8984                 return ApkAssets.loadFromPath(path);
8985             } catch (IOException e) {
8986                 throw new PackageParserException(INSTALL_FAILED_INVALID_APK,
8987                         "Failed to load APK at path " + path, e);
8988             }
8989         }
8990 
8991         @Override
getBaseAssetManager()8992         public AssetManager getBaseAssetManager() throws PackageParserException {
8993             if (mCachedAssetManager != null) {
8994                 return mCachedAssetManager;
8995             }
8996 
8997             ApkAssets[] apkAssets = new ApkAssets[(mSplitCodePaths != null
8998                     ? mSplitCodePaths.length : 0) + 1];
8999 
9000             mBaseApkAssets = loadApkAssets(mBaseCodePath, mFlags);
9001 
9002             // Load the base.
9003             int splitIdx = 0;
9004             apkAssets[splitIdx++] = mBaseApkAssets;
9005 
9006             // Load any splits.
9007             if (!ArrayUtils.isEmpty(mSplitCodePaths)) {
9008                 for (String apkPath : mSplitCodePaths) {
9009                     apkAssets[splitIdx++] = loadApkAssets(apkPath, mFlags);
9010                 }
9011             }
9012 
9013             AssetManager assets = new AssetManager();
9014             assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9015                     Build.VERSION.RESOURCES_SDK_INT);
9016             assets.setApkAssets(apkAssets, false /*invalidateCaches*/);
9017 
9018             mCachedAssetManager = assets;
9019             return mCachedAssetManager;
9020         }
9021 
9022         @Override
getSplitAssetManager(int splitIdx)9023         public AssetManager getSplitAssetManager(int splitIdx) throws PackageParserException {
9024             return getBaseAssetManager();
9025         }
9026 
9027         @Override
close()9028         public void close() throws Exception {
9029             IoUtils.closeQuietly(mCachedAssetManager);
9030         }
9031 
9032         @Override
getBaseApkAssets()9033         public ApkAssets getBaseApkAssets() {
9034             return mBaseApkAssets;
9035         }
9036     }
9037 
9038     /**
9039      * Loads AssetManagers for splits and their dependencies. This SplitAssetLoader implementation
9040      * is to be used when an application opts-in to isolated split loading.
9041      * @hide
9042      * @deprecated Do not use. New changes should use
9043      * {@link android.content.pm.split.SplitAssetDependencyLoader} instead.
9044      */
9045     @Deprecated
9046     private static class SplitAssetDependencyLoader extends
9047             SplitDependencyLoader<PackageParserException> implements SplitAssetLoader {
9048         private final String[] mSplitPaths;
9049         private final @ParseFlags int mFlags;
9050         private final ApkAssets[][] mCachedSplitApks;
9051         private final AssetManager[] mCachedAssetManagers;
9052 
SplitAssetDependencyLoader(PackageLite pkg, SparseArray<int[]> dependencies, @ParseFlags int flags)9053         SplitAssetDependencyLoader(PackageLite pkg,
9054                 SparseArray<int[]> dependencies, @ParseFlags int flags) {
9055             super(dependencies);
9056 
9057             // The base is inserted into index 0, so we need to shift all the splits by 1.
9058             mSplitPaths = new String[pkg.splitCodePaths.length + 1];
9059             mSplitPaths[0] = pkg.baseCodePath;
9060             System.arraycopy(pkg.splitCodePaths, 0, mSplitPaths, 1, pkg.splitCodePaths.length);
9061 
9062             mFlags = flags;
9063             mCachedSplitApks = new ApkAssets[mSplitPaths.length][];
9064             mCachedAssetManagers = new AssetManager[mSplitPaths.length];
9065         }
9066 
9067         @Override
isSplitCached(int splitIdx)9068         protected boolean isSplitCached(int splitIdx) {
9069             return mCachedAssetManagers[splitIdx] != null;
9070         }
9071 
loadApkAssets(String path, @ParseFlags int flags)9072         private static ApkAssets loadApkAssets(String path, @ParseFlags int flags)
9073                 throws PackageParserException {
9074             if ((flags & PackageParser.PARSE_MUST_BE_APK) != 0 && !PackageParser.isApkPath(path)) {
9075                 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
9076                         "Invalid package file: " + path);
9077             }
9078 
9079             try {
9080                 return ApkAssets.loadFromPath(path);
9081             } catch (IOException e) {
9082                 throw new PackageParserException(PackageManager.INSTALL_FAILED_INVALID_APK,
9083                         "Failed to load APK at path " + path, e);
9084             }
9085         }
9086 
createAssetManagerWithAssets(ApkAssets[] apkAssets)9087         private static AssetManager createAssetManagerWithAssets(ApkAssets[] apkAssets) {
9088             final AssetManager assets = new AssetManager();
9089             assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9090                     Build.VERSION.RESOURCES_SDK_INT);
9091             assets.setApkAssets(apkAssets, false /*invalidateCaches*/);
9092             return assets;
9093         }
9094 
9095         @Override
constructSplit(int splitIdx, @NonNull int[] configSplitIndices, int parentSplitIdx)9096         protected void constructSplit(int splitIdx, @NonNull int[] configSplitIndices,
9097                 int parentSplitIdx) throws PackageParserException {
9098             final ArrayList<ApkAssets> assets = new ArrayList<>();
9099 
9100             // Include parent ApkAssets.
9101             if (parentSplitIdx >= 0) {
9102                 Collections.addAll(assets, mCachedSplitApks[parentSplitIdx]);
9103             }
9104 
9105             // Include this ApkAssets.
9106             assets.add(loadApkAssets(mSplitPaths[splitIdx], mFlags));
9107 
9108             // Load and include all config splits for this feature.
9109             for (int configSplitIdx : configSplitIndices) {
9110                 assets.add(loadApkAssets(mSplitPaths[configSplitIdx], mFlags));
9111             }
9112 
9113             // Cache the results.
9114             mCachedSplitApks[splitIdx] = assets.toArray(new ApkAssets[assets.size()]);
9115             mCachedAssetManagers[splitIdx] = createAssetManagerWithAssets(
9116                     mCachedSplitApks[splitIdx]);
9117         }
9118 
9119         @Override
getBaseAssetManager()9120         public AssetManager getBaseAssetManager() throws PackageParserException {
9121             loadDependenciesForSplit(0);
9122             return mCachedAssetManagers[0];
9123         }
9124 
9125         @Override
getSplitAssetManager(int idx)9126         public AssetManager getSplitAssetManager(int idx) throws PackageParserException {
9127             // Since we insert the base at position 0, and PackageParser keeps splits separate from
9128             // the base, we need to adjust the index.
9129             loadDependenciesForSplit(idx + 1);
9130             return mCachedAssetManagers[idx + 1];
9131         }
9132 
9133         @Override
close()9134         public void close() throws Exception {
9135             for (AssetManager assets : mCachedAssetManagers) {
9136                 IoUtils.closeQuietly(assets);
9137             }
9138         }
9139 
9140         @Override
getBaseApkAssets()9141         public ApkAssets getBaseApkAssets() {
9142             return mCachedSplitApks[0][0];
9143         }
9144     }
9145 
9146 
9147 
isMatch(@onNull FrameworkPackageUserState state, ComponentInfo componentInfo, long flags)9148     public static boolean isMatch(@NonNull FrameworkPackageUserState state,
9149             ComponentInfo componentInfo, long flags) {
9150         return isMatch(state, componentInfo.applicationInfo.isSystemApp(),
9151                 componentInfo.applicationInfo.enabled, componentInfo.enabled,
9152                 componentInfo.directBootAware, componentInfo.name, flags);
9153     }
9154 
isMatch(@onNull FrameworkPackageUserState state, boolean isSystem, boolean isPackageEnabled, ComponentInfo component, long flags)9155     public static boolean isMatch(@NonNull FrameworkPackageUserState state, boolean isSystem,
9156             boolean isPackageEnabled, ComponentInfo component, long flags) {
9157         return isMatch(state, isSystem, isPackageEnabled, component.isEnabled(),
9158                 component.directBootAware, component.name, flags);
9159     }
9160 
9161     /**
9162      * Test if the given component is considered installed, enabled and a match for the given
9163      * flags.
9164      *
9165      * <p>
9166      * Expects at least one of {@link PackageManager#MATCH_DIRECT_BOOT_AWARE} and {@link
9167      * PackageManager#MATCH_DIRECT_BOOT_UNAWARE} are specified in {@code flags}.
9168      * </p>
9169      */
isMatch(@onNull FrameworkPackageUserState state, boolean isSystem, boolean isPackageEnabled, boolean isComponentEnabled, boolean isComponentDirectBootAware, String componentName, long flags)9170     public static boolean isMatch(@NonNull FrameworkPackageUserState state, boolean isSystem,
9171             boolean isPackageEnabled, boolean isComponentEnabled,
9172             boolean isComponentDirectBootAware, String componentName, long flags) {
9173         final boolean matchUninstalled = (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0;
9174         if (!isAvailable(state, flags) && !(isSystem && matchUninstalled)) {
9175             return reportIfDebug(false, flags);
9176         }
9177 
9178         if (!isEnabled(state, isPackageEnabled, isComponentEnabled, componentName, flags)) {
9179             return reportIfDebug(false, flags);
9180         }
9181 
9182         if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
9183             if (!isSystem) {
9184                 return reportIfDebug(false, flags);
9185             }
9186         }
9187 
9188         final boolean matchesUnaware = ((flags & PackageManager.MATCH_DIRECT_BOOT_UNAWARE) != 0)
9189                 && !isComponentDirectBootAware;
9190         final boolean matchesAware = ((flags & PackageManager.MATCH_DIRECT_BOOT_AWARE) != 0)
9191                 && isComponentDirectBootAware;
9192         return reportIfDebug(matchesUnaware || matchesAware, flags);
9193     }
9194 
isAvailable(@onNull FrameworkPackageUserState state, long flags)9195     public static boolean isAvailable(@NonNull FrameworkPackageUserState state, long flags) {
9196         // True if it is installed for this user and it is not hidden. If it is hidden,
9197         // still return true if the caller requested MATCH_UNINSTALLED_PACKAGES
9198         final boolean matchAnyUser = (flags & PackageManager.MATCH_ANY_USER) != 0;
9199         final boolean matchUninstalled = (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0;
9200         return matchAnyUser
9201                 || (state.isInstalled()
9202                 && (!state.isHidden() || matchUninstalled));
9203     }
9204 
reportIfDebug(boolean result, long flags)9205     public static boolean reportIfDebug(boolean result, long flags) {
9206         if (DEBUG_PARSER && !result) {
9207             Slog.i(TAG, "No match!; flags: "
9208                     + DebugUtils.flagsToString(PackageManager.class, "MATCH_", flags) + " "
9209                     + Debug.getCaller());
9210         }
9211         return result;
9212     }
9213 
isEnabled(@onNull FrameworkPackageUserState state, ComponentInfo componentInfo, long flags)9214     public static boolean isEnabled(@NonNull FrameworkPackageUserState state, ComponentInfo componentInfo,
9215             long flags) {
9216         return isEnabled(state, componentInfo.applicationInfo.enabled, componentInfo.enabled,
9217                 componentInfo.name, flags);
9218     }
9219 
isEnabled(@onNull FrameworkPackageUserState state, boolean isPackageEnabled, ComponentInfo parsedComponent, long flags)9220     public static boolean isEnabled(@NonNull FrameworkPackageUserState state, boolean isPackageEnabled,
9221             ComponentInfo parsedComponent, long flags) {
9222         return isEnabled(state, isPackageEnabled, parsedComponent.isEnabled(),
9223                 parsedComponent.name, flags);
9224     }
9225 
9226     /**
9227      * Test if the given component is considered enabled.
9228      */
isEnabled(@onNull FrameworkPackageUserState state, boolean isPackageEnabled, boolean isComponentEnabled, String componentName, long flags)9229     public static boolean isEnabled(@NonNull FrameworkPackageUserState state,
9230             boolean isPackageEnabled, boolean isComponentEnabled, String componentName,
9231             long flags) {
9232         if ((flags & MATCH_DISABLED_COMPONENTS) != 0) {
9233             return true;
9234         }
9235 
9236         // First check if the overall package is disabled; if the package is
9237         // enabled then fall through to check specific component
9238         switch (state.getEnabledState()) {
9239             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
9240             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
9241                 return false;
9242             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
9243                 if ((flags & MATCH_DISABLED_UNTIL_USED_COMPONENTS) == 0) {
9244                     return false;
9245                 }
9246                 // fallthrough
9247             case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
9248                 if (!isPackageEnabled) {
9249                     return false;
9250                 }
9251                 // fallthrough
9252             case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
9253                 break;
9254         }
9255 
9256         // Check if component has explicit state before falling through to
9257         // the manifest default
9258         if (state.isComponentEnabled(componentName)) {
9259             return true;
9260         } else if (state.isComponentDisabled(componentName)) {
9261             return false;
9262         }
9263 
9264         return isComponentEnabled;
9265     }
9266 
9267     /**
9268      * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
9269      */
writeKeySetMapping(@onNull Parcel dest, @NonNull Map<String, ArraySet<PublicKey>> keySetMapping)9270     public static void writeKeySetMapping(@NonNull Parcel dest,
9271             @NonNull Map<String, ArraySet<PublicKey>> keySetMapping) {
9272         if (keySetMapping == null) {
9273             dest.writeInt(-1);
9274             return;
9275         }
9276 
9277         final int N = keySetMapping.size();
9278         dest.writeInt(N);
9279 
9280         for (String key : keySetMapping.keySet()) {
9281             dest.writeString(key);
9282             ArraySet<PublicKey> keys = keySetMapping.get(key);
9283             if (keys == null) {
9284                 dest.writeInt(-1);
9285                 continue;
9286             }
9287 
9288             final int M = keys.size();
9289             dest.writeInt(M);
9290             for (int j = 0; j < M; j++) {
9291                 dest.writeSerializable(keys.valueAt(j));
9292             }
9293         }
9294     }
9295 
9296     /**
9297      * Reads a keyset mapping from the given parcel at the given data position. May return
9298      * {@code null} if the serialized mapping was {@code null}.
9299      */
9300     @NonNull
readKeySetMapping(@onNull Parcel in)9301     public static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(@NonNull Parcel in) {
9302         final int N = in.readInt();
9303         if (N == -1) {
9304             return null;
9305         }
9306 
9307         ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
9308         for (int i = 0; i < N; ++i) {
9309             String key = in.readString();
9310             final int M = in.readInt();
9311             if (M == -1) {
9312                 keySetMapping.put(key, null);
9313                 continue;
9314             }
9315 
9316             ArraySet<PublicKey> keys = new ArraySet<>(M);
9317             for (int j = 0; j < M; ++j) {
9318                 PublicKey pk =
9319                         in.readSerializable(PublicKey.class.getClassLoader(), PublicKey.class);
9320                 keys.add(pk);
9321             }
9322 
9323             keySetMapping.put(key, keys);
9324         }
9325 
9326         return keySetMapping;
9327     }
9328 
getSeinfoUser(FrameworkPackageUserState userState)9329     public static String getSeinfoUser(FrameworkPackageUserState userState) {
9330         if (userState.isInstantApp()) {
9331             return ":ephemeralapp:complete";
9332         }
9333         return ":complete";
9334     }
9335 }
9336