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