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