OSDN Git Service

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