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