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