blob: 2093124d5b8a644a98e91771c61db01517b4eb2b [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
17package android.content.pm;
18
Wale Ogunwaled26176f2016-01-25 20:04:04 -080019import com.android.internal.R;
20import com.android.internal.util.ArrayUtils;
21import com.android.internal.util.XmlUtils;
22
23import org.xmlpull.v1.XmlPullParser;
24import org.xmlpull.v1.XmlPullParserException;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070025
Dianne Hackborn852975d2014-08-22 17:42:43 -070026import android.app.ActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.content.ComponentName;
28import android.content.Intent;
29import android.content.IntentFilter;
30import android.content.res.AssetManager;
31import android.content.res.Configuration;
32import android.content.res.Resources;
33import android.content.res.TypedArray;
34import android.content.res.XmlResourceParser;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -070035import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.os.Bundle;
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -070037import android.os.FileUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.os.PatternMatcher;
Todd Kennedy27c24fb2015-09-17 16:49:25 -070039import android.os.Trace;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070040import android.os.UserHandle;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -070041import android.text.TextUtils;
Jeff Sharkey275e0852014-06-17 18:18:49 -070042import android.util.ArrayMap;
43import android.util.ArraySet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.util.AttributeSet;
Kenny Root05ca4c92011-09-15 10:36:25 -070045import android.util.Base64;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.util.DisplayMetrics;
Kenny Root05ca4c92011-09-15 10:36:25 -070047import android.util.Log;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070048import android.util.Pair;
Kenny Rootd2d29252011-08-08 11:27:57 -070049import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.util.TypedValue;
Alex Klyubine4157182016-01-05 13:27:05 -080051import android.util.apk.ApkSignatureSchemeV2Verifier;
Jeff Sharkeyc5967e92016-01-07 18:50:29 -070052import android.util.jar.StrictJarFile;
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -070053import android.view.Gravity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054
55import java.io.File;
56import java.io.IOException;
57import java.io.InputStream;
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -070058import java.io.PrintWriter;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070059import java.security.GeneralSecurityException;
Kenny Root05ca4c92011-09-15 10:36:25 -070060import java.security.KeyFactory;
61import java.security.NoSuchAlgorithmException;
62import java.security.PublicKey;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import java.security.cert.Certificate;
64import java.security.cert.CertificateEncodingException;
Kenny Root05ca4c92011-09-15 10:36:25 -070065import java.security.spec.EncodedKeySpec;
66import java.security.spec.InvalidKeySpecException;
67import java.security.spec.X509EncodedKeySpec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068import java.util.ArrayList;
Dianne Hackbornffcda102014-04-24 13:06:27 -070069import java.util.Arrays;
Jeff Sharkey275e0852014-06-17 18:18:49 -070070import java.util.Collections;
71import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import java.util.Iterator;
Kenny Root05ca4c92011-09-15 10:36:25 -070073import java.util.List;
Geremy Condraf1bcca82013-01-07 22:35:24 -080074import java.util.Set;
Jeff Sharkey275e0852014-06-17 18:18:49 -070075import java.util.concurrent.atomic.AtomicReference;
Kenny Root6c918ce2013-04-02 14:04:24 -070076import java.util.zip.ZipEntry;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077
Wale Ogunwaled26176f2016-01-25 20:04:04 -080078import libcore.io.IoUtils;
79
80import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
81import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
Wale Ogunwaled829d362016-02-10 19:24:49 -080082import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
Wale Ogunwaled26176f2016-01-25 20:04:04 -080083import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
84import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
85import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
86import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Rubin Xubf67c9c2016-04-20 17:09:38 +010087import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
Wale Ogunwale6afdf912016-01-30 13:01:33 -080088import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES;
Wale Ogunwaled26176f2016-01-25 20:04:04 -080089import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
90import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
91import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
92import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
93import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
94import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
95import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
96import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
97import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
98
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099/**
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700100 * Parser for package files (APKs) on disk. This supports apps packaged either
101 * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
102 * APKs in a single directory.
103 * <p>
104 * Apps packaged as multiple APKs always consist of a single "base" APK (with a
105 * {@code null} split name) and zero or more "split" APKs (with unique split
106 * names). Any subset of those split APKs are a valid install, as long as the
107 * following constraints are met:
108 * <ul>
109 * <li>All APKs must have the exact same package name, version code, and signing
110 * certificates.
111 * <li>All APKs must have unique split names.
112 * <li>All installations must contain a single base APK.
113 * </ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700115 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116 */
117public class PackageParser {
Kenny Rootd2d29252011-08-08 11:27:57 -0700118 private static final boolean DEBUG_JAR = false;
119 private static final boolean DEBUG_PARSER = false;
120 private static final boolean DEBUG_BACKUP = false;
121
Svet Ganova7532cf2016-05-02 08:13:17 -0700122 private static final boolean MULTI_PACKAGE_APK_ENABLED = false;
Svet Ganov354cd3c2015-12-17 11:35:04 -0800123 private static final int MAX_PACKAGES_PER_APK = 5;
124
Todd Kennedy66c55532016-02-26 16:22:11 -0800125 public static final int APK_SIGNING_UNKNOWN = 0;
126 public static final int APK_SIGNING_V1 = 1;
127 public static final int APK_SIGNING_V2 = 2;
128
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700129 // TODO: switch outError users to PackageParserException
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700130 // TODO: refactor "codePath" to "apkPath"
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700131
Kenny Rootbcc954d2011-08-08 16:19:08 -0700132 /** File name in an APK for the Android manifest. */
133 private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
134
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700135 /** Path prefix for apps on expanded storage */
136 private static final String MNT_EXPAND = "/mnt/expand/";
137
Svet Ganov354cd3c2015-12-17 11:35:04 -0800138 private static final String TAG_MANIFEST = "manifest";
139 private static final String TAG_APPLICATION = "application";
140 private static final String TAG_OVERLAY = "overlay";
141 private static final String TAG_KEY_SETS = "key-sets";
142 private static final String TAG_PERMISSION_GROUP = "permission-group";
143 private static final String TAG_PERMISSION = "permission";
144 private static final String TAG_PERMISSION_TREE = "permission-tree";
145 private static final String TAG_USES_PERMISSION = "uses-permission";
146 private static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
147 private static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23";
148 private static final String TAG_USES_CONFIGURATION = "uses-configuration";
149 private static final String TAG_USES_FEATURE = "uses-feature";
150 private static final String TAG_FEATURE_GROUP = "feature-group";
151 private static final String TAG_USES_SDK = "uses-sdk";
152 private static final String TAG_SUPPORT_SCREENS = "supports-screens";
153 private static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
154 private static final String TAG_INSTRUMENTATION = "instrumentation";
155 private static final String TAG_ORIGINAL_PACKAGE = "original-package";
156 private static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
157 private static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
158 private static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
159 private static final String TAG_SUPPORTS_INPUT = "supports-input";
160 private static final String TAG_EAT_COMMENT = "eat-comment";
161 private static final String TAG_PACKAGE = "package";
Todd Kennedyfdd241a2016-04-28 12:26:53 -0700162 private static final String TAG_RESTRICT_UPDATE = "restrict-update";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800163
164 // These are the tags supported by child packages
165 private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>();
166 static {
167 CHILD_PACKAGE_TAGS.add(TAG_APPLICATION);
168 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION);
169 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_M);
170 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_23);
171 CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION);
172 CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE);
173 CHILD_PACKAGE_TAGS.add(TAG_FEATURE_GROUP);
174 CHILD_PACKAGE_TAGS.add(TAG_USES_SDK);
175 CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS);
176 CHILD_PACKAGE_TAGS.add(TAG_INSTRUMENTATION);
177 CHILD_PACKAGE_TAGS.add(TAG_USES_GL_TEXTURE);
178 CHILD_PACKAGE_TAGS.add(TAG_COMPATIBLE_SCREENS);
179 CHILD_PACKAGE_TAGS.add(TAG_SUPPORTS_INPUT);
180 CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
181 }
182
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700183 /** @hide */
184 public static class NewPermissionInfo {
185 public final String name;
186 public final int sdkVersion;
187 public final int fileVersion;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700188
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700189 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
190 this.name = name;
191 this.sdkVersion = sdkVersion;
192 this.fileVersion = fileVersion;
193 }
194 }
Dianne Hackborn79245122012-03-12 10:51:26 -0700195
196 /** @hide */
197 public static class SplitPermissionInfo {
198 public final String rootPerm;
199 public final String[] newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700200 public final int targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700201
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700202 public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
Dianne Hackborn79245122012-03-12 10:51:26 -0700203 this.rootPerm = rootPerm;
204 this.newPerms = newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700205 this.targetSdk = targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700206 }
207 }
208
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700209 /**
210 * List of new permissions that have been added since 1.0.
211 * NOTE: These must be declared in SDK version order, with permissions
212 * added to older SDKs appearing before those added to newer SDKs.
Dianne Hackborn79245122012-03-12 10:51:26 -0700213 * If sdkVersion is 0, then this is not a permission that we want to
214 * automatically add to older apps, but we do want to allow it to be
215 * granted during a platform update.
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700216 * @hide
217 */
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700218 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
219 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -0700220 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700221 android.os.Build.VERSION_CODES.DONUT, 0),
222 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
223 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700224 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225
Dianne Hackborn79245122012-03-12 10:51:26 -0700226 /**
227 * List of permissions that have been split into more granular or dependent
228 * permissions.
229 * @hide
230 */
231 public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
232 new PackageParser.SplitPermissionInfo[] {
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700233 // READ_EXTERNAL_STORAGE is always required when an app requests
234 // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
235 // write access without read access. The hack here with the target
236 // target SDK version ensures that this grant is always done.
Dianne Hackborn79245122012-03-12 10:51:26 -0700237 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700238 new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700239 android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700240 new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
241 new String[] { android.Manifest.permission.READ_CALL_LOG },
242 android.os.Build.VERSION_CODES.JELLY_BEAN),
243 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
244 new String[] { android.Manifest.permission.WRITE_CALL_LOG },
245 android.os.Build.VERSION_CODES.JELLY_BEAN)
Dianne Hackborn79245122012-03-12 10:51:26 -0700246 };
247
Jeff Sharkey275e0852014-06-17 18:18:49 -0700248 /**
249 * @deprecated callers should move to explicitly passing around source path.
250 */
251 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 private String mArchiveSourcePath;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700255 private boolean mOnlyCoreApps;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700256 private DisplayMetrics mMetrics;
257
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700258 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700259 private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260
261 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
262
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700263 private static boolean sCompatibilityModeEnabled = true;
Amith Yamasani655d0e22013-06-12 14:19:10 -0700264 private static final int PARSE_DEFAULT_INSTALL_LOCATION =
265 PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700266
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700267 static class ParsePackageItemArgs {
268 final Package owner;
269 final String[] outError;
270 final int nameRes;
271 final int labelRes;
272 final int iconRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700273 final int roundIconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700274 final int logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800275 final int bannerRes;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700276
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700277 String tag;
278 TypedArray sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700279
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700280 ParsePackageItemArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700281 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
282 int _bannerRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700283 owner = _owner;
284 outError = _outError;
285 nameRes = _nameRes;
286 labelRes = _labelRes;
287 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700288 logoRes = _logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800289 bannerRes = _bannerRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700290 roundIconRes = _roundIconRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700291 }
292 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700293
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700294 static class ParseComponentArgs extends ParsePackageItemArgs {
295 final String[] sepProcesses;
296 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800297 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700298 final int enabledRes;
299 int flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700300
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700301 ParseComponentArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700302 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
303 int _bannerRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800304 String[] _sepProcesses, int _processRes,
305 int _descriptionRes, int _enabledRes) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700306 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _roundIconRes, _logoRes,
307 _bannerRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700308 sepProcesses = _sepProcesses;
309 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800310 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700311 enabledRes = _enabledRes;
312 }
313 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800314
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700315 /**
Jeff Sharkey73767b92014-07-04 20:18:13 -0700316 * Lightweight parsed details about a single package.
317 */
318 public static class PackageLite {
319 public final String packageName;
320 public final int versionCode;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700321 public final int installLocation;
322 public final VerifierInfo[] verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700323
324 /** Names of any split APKs, ordered by parsed splitName */
325 public final String[] splitNames;
326
327 /**
328 * Path where this package was found on disk. For monolithic packages
329 * this is path to single base APK file; for cluster packages this is
330 * path to the cluster directory.
331 */
332 public final String codePath;
333
334 /** Path of base APK */
335 public final String baseCodePath;
336 /** Paths of any split APKs, ordered by parsed splitName */
337 public final String[] splitCodePaths;
338
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800339 /** Revision code of base APK */
340 public final int baseRevisionCode;
341 /** Revision codes of any split APKs, ordered by parsed splitName */
342 public final int[] splitRevisionCodes;
343
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700344 public final boolean coreApp;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100345 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800346 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700347 public final boolean extractNativeLibs;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100348
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700349 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800350 String[] splitCodePaths, int[] splitRevisionCodes) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700351 this.packageName = baseApk.packageName;
352 this.versionCode = baseApk.versionCode;
353 this.installLocation = baseApk.installLocation;
354 this.verifiers = baseApk.verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700355 this.splitNames = splitNames;
356 this.codePath = codePath;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700357 this.baseCodePath = baseApk.codePath;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700358 this.splitCodePaths = splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800359 this.baseRevisionCode = baseApk.revisionCode;
360 this.splitRevisionCodes = splitRevisionCodes;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700361 this.coreApp = baseApk.coreApp;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100362 this.multiArch = baseApk.multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800363 this.use32bitAbi = baseApk.use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700364 this.extractNativeLibs = baseApk.extractNativeLibs;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700365 }
366
367 public List<String> getAllCodePaths() {
368 ArrayList<String> paths = new ArrayList<>();
369 paths.add(baseCodePath);
370 if (!ArrayUtils.isEmpty(splitCodePaths)) {
371 Collections.addAll(paths, splitCodePaths);
372 }
373 return paths;
374 }
375 }
376
377 /**
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700378 * Lightweight parsed details about a single APK file.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800379 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700380 public static class ApkLite {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700381 public final String codePath;
Kenny Root05ca4c92011-09-15 10:36:25 -0700382 public final String packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700383 public final String splitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700384 public final int versionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800385 public final int revisionCode;
Kenny Root05ca4c92011-09-15 10:36:25 -0700386 public final int installLocation;
387 public final VerifierInfo[] verifiers;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700388 public final Signature[] signatures;
Todd Kennedyd9d438a2016-04-06 14:08:14 -0700389 public final Certificate[][] certificates;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700390 public final boolean coreApp;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100391 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800392 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700393 public final boolean extractNativeLibs;
Kenny Root05ca4c92011-09-15 10:36:25 -0700394
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700395 public ApkLite(String codePath, String packageName, String splitName, int versionCode,
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800396 int revisionCode, int installLocation, List<VerifierInfo> verifiers,
Todd Kennedyd9d438a2016-04-06 14:08:14 -0700397 Signature[] signatures, Certificate[][] certificates, boolean coreApp,
398 boolean multiArch, boolean use32bitAbi, boolean extractNativeLibs) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700399 this.codePath = codePath;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800400 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700401 this.splitName = splitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700402 this.versionCode = versionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800403 this.revisionCode = revisionCode;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800404 this.installLocation = installLocation;
Kenny Root05ca4c92011-09-15 10:36:25 -0700405 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700406 this.signatures = signatures;
Todd Kennedyd9d438a2016-04-06 14:08:14 -0700407 this.certificates = certificates;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700408 this.coreApp = coreApp;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100409 this.multiArch = multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800410 this.use32bitAbi = use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700411 this.extractNativeLibs = extractNativeLibs;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800412 }
413 }
414
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700415 private ParsePackageItemArgs mParseInstrumentationArgs;
416 private ParseComponentArgs mParseActivityArgs;
417 private ParseComponentArgs mParseActivityAliasArgs;
418 private ParseComponentArgs mParseServiceArgs;
419 private ParseComponentArgs mParseProviderArgs;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 /** If set to true, we will only allow package files that exactly match
422 * the DTD. Otherwise, we try to get as much from the package as we
423 * can without failing. This should normally be set to false, to
424 * support extensions to the DTD in future versions. */
425 private static final boolean RIGID_PARSER = false;
426
427 private static final String TAG = "PackageParser";
428
Jeff Sharkey275e0852014-06-17 18:18:49 -0700429 public PackageParser() {
430 mMetrics = new DisplayMetrics();
431 mMetrics.setToDefaults();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700432 }
433
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 public void setSeparateProcesses(String[] procs) {
435 mSeparateProcesses = procs;
436 }
437
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700438 /**
439 * Flag indicating this parser should only consider apps with
440 * {@code coreApp} manifest attribute to be valid apps. This is useful when
441 * creating a minimalist boot environment.
442 */
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700443 public void setOnlyCoreApps(boolean onlyCoreApps) {
444 mOnlyCoreApps = onlyCoreApps;
445 }
446
Jeff Sharkey275e0852014-06-17 18:18:49 -0700447 public void setDisplayMetrics(DisplayMetrics metrics) {
448 mMetrics = metrics;
449 }
450
Jeff Sharkey73767b92014-07-04 20:18:13 -0700451 public static final boolean isApkFile(File file) {
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700452 return isApkPath(file.getName());
453 }
454
455 private static boolean isApkPath(String path) {
456 return path.endsWith(".apk");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 }
458
459 /**
460 * Generate and return the {@link PackageInfo} for a parsed package.
461 *
462 * @param p the parsed package.
463 * @param flags indicating which optional information is included.
464 */
465 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Dianne Hackborne639da72012-02-21 15:11:13 -0800466 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svet Ganov3695b8a2015-03-24 16:30:25 -0700467 Set<String> grantedPermissions, PackageUserState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468
Amith Yamasani483f3b02012-03-13 16:08:00 -0700469 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700470 grantedPermissions, state, UserHandle.getCallingUserId());
471 }
472
Amith Yamasani655d0e22013-06-12 14:19:10 -0700473 /**
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700474 * Returns true if the package is installed and not hidden, or if the caller
475 * explicitly wanted all uninstalled and hidden packages as well.
Amith Yamasani655d0e22013-06-12 14:19:10 -0700476 */
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700477 private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state) {
478 return (state.installed && !state.hidden)
Amith Yamasani655d0e22013-06-12 14:19:10 -0700479 || (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700480 }
481
Christopher Tateba629da2013-11-13 17:42:28 -0800482 public static boolean isAvailable(PackageUserState state) {
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700483 return checkUseInstalledOrHidden(0, state);
Christopher Tateba629da2013-11-13 17:42:28 -0800484 }
485
Amith Yamasani13593602012-03-22 16:16:17 -0700486 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Amith Yamasani483f3b02012-03-13 16:08:00 -0700487 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svetoslavc6d1c342015-02-26 14:44:43 -0800488 Set<String> grantedPermissions, PackageUserState state, int userId) {
Jeff Sharkeyc5967e92016-01-07 18:50:29 -0700489 if (!checkUseInstalledOrHidden(flags, state) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700490 return null;
491 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800492 PackageInfo pi = new PackageInfo();
493 pi.packageName = p.packageName;
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700494 pi.splitNames = p.splitNames;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 pi.versionCode = p.mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800496 pi.baseRevisionCode = p.baseRevisionCode;
497 pi.splitRevisionCodes = p.splitRevisionCodes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800498 pi.versionName = p.mVersionName;
499 pi.sharedUserId = p.mSharedUserId;
500 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700501 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800502 pi.installLocation = p.installLocation;
Jeff Hao272bf3a2014-10-08 13:34:43 -0700503 pi.coreApp = p.coreApp;
Amith Yamasani0d8750d2013-05-01 15:25:28 -0700504 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
505 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
506 pi.requiredForAllUsers = p.mRequiredForAllUsers;
507 }
Amith Yamasani0ac1fc92013-03-27 18:56:08 -0700508 pi.restrictedAccountType = p.mRestrictedAccountType;
Amith Yamasaniccbe3892013-04-12 17:52:42 -0700509 pi.requiredAccountType = p.mRequiredAccountType;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100510 pi.overlayTarget = p.mOverlayTarget;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700511 pi.firstInstallTime = firstInstallTime;
512 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800513 if ((flags&PackageManager.GET_GIDS) != 0) {
514 pi.gids = gids;
515 }
516 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700517 int N = p.configPreferences != null ? p.configPreferences.size() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518 if (N > 0) {
519 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700520 p.configPreferences.toArray(pi.configPreferences);
521 }
522 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
523 if (N > 0) {
524 pi.reqFeatures = new FeatureInfo[N];
525 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800526 }
Adam Lesinskid3edfde2014-08-08 17:32:44 -0700527 N = p.featureGroups != null ? p.featureGroups.size() : 0;
528 if (N > 0) {
529 pi.featureGroups = new FeatureGroupInfo[N];
530 p.featureGroups.toArray(pi.featureGroups);
531 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700533 if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
534 final int N = p.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700536 int num = 0;
537 final ActivityInfo[] res = new ActivityInfo[N];
538 for (int i = 0; i < N; i++) {
539 final Activity a = p.activities.get(i);
540 if (state.isMatch(a.info, flags)) {
541 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 }
543 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700544 pi.activities = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 }
546 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700547 if ((flags & PackageManager.GET_RECEIVERS) != 0) {
548 final int N = p.receivers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700550 int num = 0;
551 final ActivityInfo[] res = new ActivityInfo[N];
552 for (int i = 0; i < N; i++) {
553 final Activity a = p.receivers.get(i);
554 if (state.isMatch(a.info, flags)) {
555 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 }
557 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700558 pi.receivers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800559 }
560 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700561 if ((flags & PackageManager.GET_SERVICES) != 0) {
562 final int N = p.services.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700564 int num = 0;
565 final ServiceInfo[] res = new ServiceInfo[N];
566 for (int i = 0; i < N; i++) {
567 final Service s = p.services.get(i);
568 if (state.isMatch(s.info, flags)) {
569 res[num++] = generateServiceInfo(s, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 }
571 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700572 pi.services = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800573 }
574 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700575 if ((flags & PackageManager.GET_PROVIDERS) != 0) {
576 final int N = p.providers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700578 int num = 0;
579 final ProviderInfo[] res = new ProviderInfo[N];
580 for (int i = 0; i < N; i++) {
581 final Provider pr = p.providers.get(i);
582 if (state.isMatch(pr.info, flags)) {
583 res[num++] = generateProviderInfo(pr, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800584 }
585 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700586 pi.providers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 }
588 }
589 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
590 int N = p.instrumentation.size();
591 if (N > 0) {
592 pi.instrumentation = new InstrumentationInfo[N];
593 for (int i=0; i<N; i++) {
594 pi.instrumentation[i] = generateInstrumentationInfo(
595 p.instrumentation.get(i), flags);
596 }
597 }
598 }
599 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
600 int N = p.permissions.size();
601 if (N > 0) {
602 pi.permissions = new PermissionInfo[N];
603 for (int i=0; i<N; i++) {
604 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
605 }
606 }
607 N = p.requestedPermissions.size();
608 if (N > 0) {
609 pi.requestedPermissions = new String[N];
Dianne Hackborne639da72012-02-21 15:11:13 -0800610 pi.requestedPermissionsFlags = new int[N];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800611 for (int i=0; i<N; i++) {
Dianne Hackborne639da72012-02-21 15:11:13 -0800612 final String perm = p.requestedPermissions.get(i);
613 pi.requestedPermissions[i] = perm;
Svet Ganov3695b8a2015-03-24 16:30:25 -0700614 // The notion of required permissions is deprecated but for compatibility.
Svetoslavc6d1c342015-02-26 14:44:43 -0800615 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800616 if (grantedPermissions != null && grantedPermissions.contains(perm)) {
617 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619 }
620 }
621 }
622 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700623 int N = (p.mSignatures != null) ? p.mSignatures.length : 0;
624 if (N > 0) {
625 pi.signatures = new Signature[N];
626 System.arraycopy(p.mSignatures, 0, pi.signatures, 0, N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800627 }
628 }
629 return pi;
630 }
631
Jeff Sharkey275e0852014-06-17 18:18:49 -0700632 private static Certificate[][] loadCertificates(StrictJarFile jarFile, ZipEntry entry)
633 throws PackageParserException {
634 InputStream is = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800635 try {
636 // We must read the stream for the JarEntry to retrieve
637 // its certificates.
Jeff Sharkey275e0852014-06-17 18:18:49 -0700638 is = jarFile.getInputStream(entry);
639 readFullyIgnoringContents(is);
640 return jarFile.getCertificateChains(entry);
641 } catch (IOException | RuntimeException e) {
642 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
643 "Failed reading " + entry.getName() + " in " + jarFile, e);
644 } finally {
645 IoUtils.closeQuietly(is);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647 }
648
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800649 public final static int PARSE_IS_SYSTEM = 1<<0;
650 public final static int PARSE_CHATTY = 1<<1;
651 public final static int PARSE_MUST_BE_APK = 1<<2;
652 public final static int PARSE_IGNORE_PROCESSES = 1<<3;
653 public final static int PARSE_FORWARD_LOCK = 1<<4;
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -0700654 public final static int PARSE_EXTERNAL_STORAGE = 1<<5;
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700655 public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
Christopher Tateccbf84f2013-05-08 15:25:41 -0700656 public final static int PARSE_IS_PRIVILEGED = 1<<7;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700657 public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700658 public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
Christopher Tatef3d939c2015-09-17 12:25:51 -0700659 public final static int PARSE_ENFORCE_CODE = 1<<10;
Todd Kennedy373f0b42015-12-16 14:45:14 -0800660 public final static int PARSE_IS_EPHEMERAL = 1<<11;
Todd Kennedyb1072712016-04-26 15:41:20 -0700661 public final static int PARSE_FORCE_SDK = 1<<12;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700662
663 private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700665 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700666 * Used to sort a set of APKs based on their split names, always placing the
667 * base APK (with {@code null} split name) first.
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700668 */
Jeff Sharkey275e0852014-06-17 18:18:49 -0700669 private static class SplitNameComparator implements Comparator<String> {
670 @Override
671 public int compare(String lhs, String rhs) {
672 if (lhs == null) {
673 return -1;
674 } else if (rhs == null) {
675 return 1;
676 } else {
677 return lhs.compareTo(rhs);
678 }
679 }
680 }
681
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700682 /**
683 * Parse only lightweight details about the package at the given location.
684 * Automatically detects if the package is a monolithic style (single APK
685 * file) or cluster style (directory of APKs).
686 * <p>
687 * This performs sanity checking on cluster style packages, such as
688 * requiring identical package name and version codes, a single base APK,
689 * and unique split names.
690 *
691 * @see PackageParser#parsePackage(File, int)
692 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700693 public static PackageLite parsePackageLite(File packageFile, int flags)
694 throws PackageParserException {
695 if (packageFile.isDirectory()) {
696 return parseClusterPackageLite(packageFile, flags);
697 } else {
698 return parseMonolithicPackageLite(packageFile, flags);
699 }
700 }
701
702 private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
703 throws PackageParserException {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700704 final ApkLite baseApk = parseApkLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700705 final String packagePath = packageFile.getAbsolutePath();
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800706 return new PackageLite(packagePath, baseApk, null, null, null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700707 }
708
709 private static PackageLite parseClusterPackageLite(File packageDir, int flags)
710 throws PackageParserException {
711 final File[] files = packageDir.listFiles();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700712 if (ArrayUtils.isEmpty(files)) {
713 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
714 "No packages found in split");
715 }
716
Jeff Sharkey275e0852014-06-17 18:18:49 -0700717 String packageName = null;
718 int versionCode = 0;
719
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700720 final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700721 for (File file : files) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700722 if (isApkFile(file)) {
723 final ApkLite lite = parseApkLite(file, flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -0700724
725 // Assert that all package names and version codes are
726 // consistent with the first one we encounter.
727 if (packageName == null) {
728 packageName = lite.packageName;
729 versionCode = lite.versionCode;
730 } else {
731 if (!packageName.equals(lite.packageName)) {
732 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
733 "Inconsistent package " + lite.packageName + " in " + file
734 + "; expected " + packageName);
735 }
736 if (versionCode != lite.versionCode) {
737 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
738 "Inconsistent version " + lite.versionCode + " in " + file
739 + "; expected " + versionCode);
740 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700741 }
742
Jeff Sharkey275e0852014-06-17 18:18:49 -0700743 // Assert that each split is defined only once
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700744 if (apks.put(lite.splitName, lite) != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700745 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
746 "Split name " + lite.splitName
747 + " defined more than once; most recent was " + file);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700748 }
749 }
750 }
751
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700752 final ApkLite baseApk = apks.remove(null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700753 if (baseApk == null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700754 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
Jeff Sharkey73767b92014-07-04 20:18:13 -0700755 "Missing base APK in " + packageDir);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700756 }
757
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700758 // Always apply deterministic ordering based on splitName
759 final int size = apks.size();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700760
Jeff Sharkey73767b92014-07-04 20:18:13 -0700761 String[] splitNames = null;
762 String[] splitCodePaths = null;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800763 int[] splitRevisionCodes = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700764 if (size > 0) {
765 splitNames = new String[size];
766 splitCodePaths = new String[size];
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800767 splitRevisionCodes = new int[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700768
769 splitNames = apks.keySet().toArray(splitNames);
770 Arrays.sort(splitNames, sSplitNameComparator);
771
772 for (int i = 0; i < size; i++) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700773 splitCodePaths[i] = apks.get(splitNames[i]).codePath;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800774 splitRevisionCodes[i] = apks.get(splitNames[i]).revisionCode;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700775 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700776 }
777
Jeff Sharkey73767b92014-07-04 20:18:13 -0700778 final String codePath = packageDir.getAbsolutePath();
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800779 return new PackageLite(codePath, baseApk, splitNames, splitCodePaths,
780 splitRevisionCodes);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700781 }
782
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700783 /**
784 * Parse the package at the given location. Automatically detects if the
785 * package is a monolithic style (single APK file) or cluster style
786 * (directory of APKs).
787 * <p>
788 * This performs sanity checking on cluster style packages, such as
789 * requiring identical package name and version codes, a single base APK,
790 * and unique split names.
791 * <p>
792 * Note that this <em>does not</em> perform signature verification; that
793 * must be done separately in {@link #collectCertificates(Package, int)}.
794 *
795 * @see #parsePackageLite(File, int)
796 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700797 public Package parsePackage(File packageFile, int flags) throws PackageParserException {
798 if (packageFile.isDirectory()) {
799 return parseClusterPackage(packageFile, flags);
800 } else {
801 return parseMonolithicPackage(packageFile, flags);
802 }
803 }
804
805 /**
806 * Parse all APKs contained in the given directory, treating them as a
807 * single package. This also performs sanity checking, such as requiring
808 * identical package name and version codes, a single base APK, and unique
809 * split names.
810 * <p>
811 * Note that this <em>does not</em> perform signature verification; that
812 * must be done separately in {@link #collectCertificates(Package, int)}.
813 */
814 private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
815 final PackageLite lite = parseClusterPackageLite(packageDir, 0);
816
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700817 if (mOnlyCoreApps && !lite.coreApp) {
818 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
819 "Not a coreApp: " + packageDir);
820 }
821
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700822 final AssetManager assets = new AssetManager();
823 try {
824 // Load the base and all splits into the AssetManager
825 // so that resources can be overriden when parsing the manifests.
826 loadApkIntoAssetManager(assets, lite.baseCodePath, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700827
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700828 if (!ArrayUtils.isEmpty(lite.splitCodePaths)) {
829 for (String path : lite.splitCodePaths) {
830 loadApkIntoAssetManager(assets, path, flags);
831 }
Jeff Sharkey73767b92014-07-04 20:18:13 -0700832 }
Jeff Sharkey73767b92014-07-04 20:18:13 -0700833
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700834 final File baseApk = new File(lite.baseCodePath);
835 final Package pkg = parseBaseApk(baseApk, assets, flags);
836 if (pkg == null) {
837 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
838 "Failed to parse base APK: " + baseApk);
839 }
840
841 if (!ArrayUtils.isEmpty(lite.splitNames)) {
842 final int num = lite.splitNames.length;
843 pkg.splitNames = lite.splitNames;
844 pkg.splitCodePaths = lite.splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800845 pkg.splitRevisionCodes = lite.splitRevisionCodes;
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700846 pkg.splitFlags = new int[num];
Alex Klyubinb9f8a522015-02-03 11:12:59 -0800847 pkg.splitPrivateFlags = new int[num];
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700848
849 for (int i = 0; i < num; i++) {
850 parseSplitApk(pkg, i, assets, flags);
851 }
852 }
853
Svet Ganov354cd3c2015-12-17 11:35:04 -0800854 pkg.setCodePath(packageDir.getAbsolutePath());
Selim Gurun2d291d82016-02-05 17:50:53 -0800855 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700856 return pkg;
857 } finally {
858 IoUtils.closeQuietly(assets);
859 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 }
861
Jeff Sharkey275e0852014-06-17 18:18:49 -0700862 /**
863 * Parse the given APK file, treating it as as a single monolithic package.
864 * <p>
865 * Note that this <em>does not</em> perform signature verification; that
866 * must be done separately in {@link #collectCertificates(Package, int)}.
Jeff Sharkeyd7460572014-07-06 20:44:55 -0700867 *
868 * @deprecated external callers should move to
869 * {@link #parsePackage(File, int)}. Eventually this method will
870 * be marked private.
Jeff Sharkey275e0852014-06-17 18:18:49 -0700871 */
Jeff Sharkeyd7460572014-07-06 20:44:55 -0700872 @Deprecated
Jeff Sharkey275e0852014-06-17 18:18:49 -0700873 public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
Tao Baic9a02372016-01-12 15:02:24 -0800874 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700875 if (mOnlyCoreApps) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700876 if (!lite.coreApp) {
877 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
878 "Not a coreApp: " + apkFile);
879 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700880 }
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700881
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700882 final AssetManager assets = new AssetManager();
883 try {
884 final Package pkg = parseBaseApk(apkFile, assets, flags);
Svet Ganov354cd3c2015-12-17 11:35:04 -0800885 pkg.setCodePath(apkFile.getAbsolutePath());
Selim Gurun2d291d82016-02-05 17:50:53 -0800886 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700887 return pkg;
888 } finally {
889 IoUtils.closeQuietly(assets);
890 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700891 }
892
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700893 private static int loadApkIntoAssetManager(AssetManager assets, String apkPath, int flags)
894 throws PackageParserException {
895 if ((flags & PARSE_MUST_BE_APK) != 0 && !isApkPath(apkPath)) {
896 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
897 "Invalid package file: " + apkPath);
898 }
899
900 // The AssetManager guarantees uniqueness for asset paths, so if this asset path
901 // already exists in the AssetManager, addAssetPath will only return the cookie
902 // assigned to it.
903 int cookie = assets.addAssetPath(apkPath);
904 if (cookie == 0) {
905 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
906 "Failed adding asset path: " + apkPath);
907 }
908 return cookie;
909 }
910
911 private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
912 throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700913 final String apkPath = apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -0700914
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700915 String volumeUuid = null;
916 if (apkPath.startsWith(MNT_EXPAND)) {
917 final int end = apkPath.indexOf('/', MNT_EXPAND.length());
918 volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
919 }
920
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 mParseError = PackageManager.INSTALL_SUCCEEDED;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700922 mArchiveSourcePath = apkFile.getAbsolutePath();
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700923
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700924 if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700926 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
927
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800928 Resources res = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700929 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700931 res = new Resources(assets, mMetrics, null);
932 assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
933 Build.VERSION.RESOURCES_SDK_INT);
934 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
935
936 final String[] outError = new String[1];
937 final Package pkg = parseBaseApk(res, parser, flags, outError);
938 if (pkg == null) {
939 throw new PackageParserException(mParseError,
940 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700942
Svet Ganov354cd3c2015-12-17 11:35:04 -0800943 pkg.setVolumeUuid(volumeUuid);
944 pkg.setApplicationVolumeUuid(volumeUuid);
945 pkg.setBaseCodePath(apkPath);
946 pkg.setSignatures(null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700947
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700948 return pkg;
949
950 } catch (PackageParserException e) {
951 throw e;
952 } catch (Exception e) {
953 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -0700954 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700955 } finally {
956 IoUtils.closeQuietly(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800958 }
959
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700960 private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700961 throws PackageParserException {
962 final String apkPath = pkg.splitCodePaths[splitIndex];
Jeff Sharkey275e0852014-06-17 18:18:49 -0700963
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700964 mParseError = PackageManager.INSTALL_SUCCEEDED;
965 mArchiveSourcePath = apkPath;
966
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700967 if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
968
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700969 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
970
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700971 Resources res = null;
972 XmlResourceParser parser = null;
973 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700974 res = new Resources(assets, mMetrics, null);
975 assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
976 Build.VERSION.RESOURCES_SDK_INT);
977 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
978
979 final String[] outError = new String[1];
980 pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
981 if (pkg == null) {
982 throw new PackageParserException(mParseError,
983 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
984 }
985
986 } catch (PackageParserException e) {
987 throw e;
988 } catch (Exception e) {
989 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -0700990 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700991 } finally {
992 IoUtils.closeQuietly(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700993 }
994 }
995
996 /**
997 * Parse the manifest of a <em>split APK</em>.
998 * <p>
999 * Note that split APKs have many more restrictions on what they're capable
1000 * of doing, so many valid features of a base APK have been carefully
1001 * omitted here.
1002 */
1003 private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001004 int splitIndex, String[] outError) throws XmlPullParserException, IOException,
1005 PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001006 AttributeSet attrs = parser;
1007
Jeff Sharkey78a13012014-07-15 20:18:34 -07001008 // We parsed manifest tag earlier; just skip past it
Svet Ganov354cd3c2015-12-17 11:35:04 -08001009 parsePackageSplitNames(parser, attrs);
Jeff Sharkey78a13012014-07-15 20:18:34 -07001010
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001011 mParseInstrumentationArgs = null;
1012 mParseActivityArgs = null;
1013 mParseServiceArgs = null;
1014 mParseProviderArgs = null;
1015
1016 int type;
1017
1018 boolean foundApp = false;
1019
1020 int outerDepth = parser.getDepth();
1021 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1022 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1023 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1024 continue;
1025 }
1026
1027 String tagName = parser.getName();
1028 if (tagName.equals("application")) {
1029 if (foundApp) {
1030 if (RIGID_PARSER) {
1031 outError[0] = "<manifest> has more than one <application>";
1032 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1033 return null;
1034 } else {
1035 Slog.w(TAG, "<manifest> has more than one <application>");
1036 XmlUtils.skipCurrentTag(parser);
1037 continue;
1038 }
1039 }
1040
1041 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001042 if (!parseSplitApplication(pkg, res, parser, flags, splitIndex, outError)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001043 return null;
1044 }
1045
1046 } else if (RIGID_PARSER) {
1047 outError[0] = "Bad element under <manifest>: "
1048 + parser.getName();
1049 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1050 return null;
1051
1052 } else {
1053 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1054 + " at " + mArchiveSourcePath + " "
1055 + parser.getPositionDescription());
1056 XmlUtils.skipCurrentTag(parser);
1057 continue;
1058 }
1059 }
1060
1061 if (!foundApp) {
1062 outError[0] = "<manifest> does not contain an <application>";
1063 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1064 }
1065
1066 return pkg;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001067 }
1068
Todd Kennedy66c55532016-02-26 16:22:11 -08001069 public static int getApkSigningVersion(Package pkg) {
1070 try {
1071 if (ApkSignatureSchemeV2Verifier.hasSignature(pkg.baseCodePath)) {
1072 return APK_SIGNING_V2;
1073 }
1074 return APK_SIGNING_V1;
1075 } catch (IOException e) {
1076 }
1077 return APK_SIGNING_UNKNOWN;
1078 }
1079
Kenny Root6c918ce2013-04-02 14:04:24 -07001080 /**
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001081 * Populates the correct packages fields with the given certificates.
1082 * <p>
1083 * This is useful when we've already processed the certificates [such as during package
1084 * installation through an installer session]. We don't re-process the archive and
1085 * simply populate the correct fields.
1086 */
1087 public static void populateCertificates(Package pkg, Certificate[][] certificates)
1088 throws PackageParserException {
1089 pkg.mCertificates = null;
1090 pkg.mSignatures = null;
1091 pkg.mSigningKeys = null;
1092
1093 pkg.mCertificates = certificates;
1094 try {
1095 pkg.mSignatures = convertToSignatures(certificates);
1096 } catch (CertificateEncodingException e) {
1097 // certificates weren't encoded properly; something went wrong
1098 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1099 "Failed to collect certificates from " + pkg.baseCodePath, e);
1100 }
1101 pkg.mSigningKeys = new ArraySet<>(certificates.length);
1102 for (int i = 0; i < certificates.length; i++) {
1103 Certificate[] signerCerts = certificates[i];
1104 Certificate signerCert = signerCerts[0];
1105 pkg.mSigningKeys.add(signerCert.getPublicKey());
1106 }
1107 // add signatures to child packages
1108 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1109 for (int i = 0; i < childCount; i++) {
1110 Package childPkg = pkg.childPackages.get(i);
1111 childPkg.mCertificates = pkg.mCertificates;
1112 childPkg.mSignatures = pkg.mSignatures;
1113 childPkg.mSigningKeys = pkg.mSigningKeys;
1114 }
1115 }
1116
1117 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -07001118 * Collect certificates from all the APKs described in the given package,
Todd Kennedy373f0b42015-12-16 14:45:14 -08001119 * populating {@link Package#mSignatures}. Also asserts that all APK
Jeff Sharkey275e0852014-06-17 18:18:49 -07001120 * contents are signed correctly and consistently.
1121 */
Todd Kennedy66c55532016-02-26 16:22:11 -08001122 public static void collectCertificates(Package pkg, int parseFlags)
1123 throws PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001124 collectCertificatesInternal(pkg, parseFlags);
1125 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1126 for (int i = 0; i < childCount; i++) {
1127 Package childPkg = pkg.childPackages.get(i);
1128 childPkg.mCertificates = pkg.mCertificates;
1129 childPkg.mSignatures = pkg.mSignatures;
1130 childPkg.mSigningKeys = pkg.mSigningKeys;
1131 }
1132 }
1133
Todd Kennedy66c55532016-02-26 16:22:11 -08001134 private static void collectCertificatesInternal(Package pkg, int parseFlags)
1135 throws PackageParserException {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001136 pkg.mCertificates = null;
1137 pkg.mSignatures = null;
1138 pkg.mSigningKeys = null;
1139
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001140 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1141 try {
Todd Kennedyf720a9d2016-04-15 09:44:36 -07001142 collectCertificates(pkg, new File(pkg.baseCodePath), parseFlags);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001143
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001144 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
1145 for (int i = 0; i < pkg.splitCodePaths.length; i++) {
Todd Kennedyf720a9d2016-04-15 09:44:36 -07001146 collectCertificates(pkg, new File(pkg.splitCodePaths[i]), parseFlags);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001147 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001148 }
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001149 } finally {
1150 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001151 }
1152 }
1153
Todd Kennedyf720a9d2016-04-15 09:44:36 -07001154 private static void collectCertificates(Package pkg, File apkFile, int parseFlags)
Jeff Sharkey275e0852014-06-17 18:18:49 -07001155 throws PackageParserException {
1156 final String apkPath = apkFile.getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157
Alex Klyubine4157182016-01-05 13:27:05 -08001158 // Try to verify the APK using APK Signature Scheme v2.
1159 boolean verified = false;
1160 {
1161 Certificate[][] allSignersCerts = null;
1162 Signature[] signatures = null;
1163 try {
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001164 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV2");
Alex Klyubine4157182016-01-05 13:27:05 -08001165 allSignersCerts = ApkSignatureSchemeV2Verifier.verify(apkPath);
1166 signatures = convertToSignatures(allSignersCerts);
1167 // APK verified using APK Signature Scheme v2.
1168 verified = true;
1169 } catch (ApkSignatureSchemeV2Verifier.SignatureNotFoundException e) {
1170 // No APK Signature Scheme v2 signature found
1171 } catch (Exception e) {
1172 // APK Signature Scheme v2 signature was found but did not verify
1173 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1174 "Failed to collect certificates from " + apkPath
1175 + " using APK Signature Scheme v2",
1176 e);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001177 } finally {
1178 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Alex Klyubine4157182016-01-05 13:27:05 -08001179 }
1180
1181 if (verified) {
1182 if (pkg.mCertificates == null) {
1183 pkg.mCertificates = allSignersCerts;
1184 pkg.mSignatures = signatures;
1185 pkg.mSigningKeys = new ArraySet<>(allSignersCerts.length);
1186 for (int i = 0; i < allSignersCerts.length; i++) {
1187 Certificate[] signerCerts = allSignersCerts[i];
1188 Certificate signerCert = signerCerts[0];
1189 pkg.mSigningKeys.add(signerCert.getPublicKey());
1190 }
1191 } else {
1192 if (!Signature.areExactMatch(pkg.mSignatures, signatures)) {
1193 throw new PackageParserException(
1194 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
1195 apkPath + " has mismatched certificates");
1196 }
1197 }
1198 // Not yet done, because we need to confirm that AndroidManifest.xml exists and,
1199 // if requested, that classes.dex exists.
1200 }
1201 }
1202
Jeff Sharkey275e0852014-06-17 18:18:49 -07001203 StrictJarFile jarFile = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001204 try {
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001205 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor");
Alex Klyubin9b59bc42016-03-24 12:02:20 -07001206 // Ignore signature stripping protections when verifying APKs from system partition.
1207 // For those APKs we only care about extracting signer certificates, and don't care
1208 // about verifying integrity.
1209 boolean signatureSchemeRollbackProtectionsEnforced =
Todd Kennedyd022ac22016-04-13 10:49:29 -07001210 (parseFlags & PARSE_IS_SYSTEM_DIR) == 0;
Alex Klyubine4157182016-01-05 13:27:05 -08001211 jarFile = new StrictJarFile(
1212 apkPath,
Alex Klyubin9b59bc42016-03-24 12:02:20 -07001213 !verified, // whether to verify JAR signature
1214 signatureSchemeRollbackProtectionsEnforced);
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001215 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001216
Jeff Sharkey275e0852014-06-17 18:18:49 -07001217 // Always verify manifest, regardless of source
1218 final ZipEntry manifestEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
1219 if (manifestEntry == null) {
1220 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1221 "Package " + apkPath + " has no manifest");
1222 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001223
Alex Klyubine4157182016-01-05 13:27:05 -08001224 // Optimization: early termination when APK already verified
1225 if (verified) {
Alex Klyubine4157182016-01-05 13:27:05 -08001226 return;
1227 }
1228
1229 // APK's integrity needs to be verified using JAR signature scheme.
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001230 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV1");
Jeff Sharkey275e0852014-06-17 18:18:49 -07001231 final List<ZipEntry> toVerify = new ArrayList<>();
1232 toVerify.add(manifestEntry);
1233
1234 // If we're parsing an untrusted package, verify all contents
Todd Kennedyd022ac22016-04-13 10:49:29 -07001235 if ((parseFlags & PARSE_IS_SYSTEM_DIR) == 0) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001236 final Iterator<ZipEntry> i = jarFile.iterator();
1237 while (i.hasNext()) {
1238 final ZipEntry entry = i.next();
1239
1240 if (entry.isDirectory()) continue;
Christopher Tatef3d939c2015-09-17 12:25:51 -07001241
1242 final String entryName = entry.getName();
1243 if (entryName.startsWith("META-INF/")) continue;
1244 if (entryName.equals(ANDROID_MANIFEST_FILENAME)) continue;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001245
1246 toVerify.add(entry);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001247 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001248 }
1249
1250 // Verify that entries are signed consistently with the first entry
1251 // we encountered. Note that for splits, certificates may have
1252 // already been populated during an earlier parse of a base APK.
1253 for (ZipEntry entry : toVerify) {
1254 final Certificate[][] entryCerts = loadCertificates(jarFile, entry);
1255 if (ArrayUtils.isEmpty(entryCerts)) {
1256 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1257 "Package " + apkPath + " has no certificates at entry "
1258 + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259 }
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001260 final Signature[] entrySignatures = convertToSignatures(entryCerts);
Kenny Rootd2d29252011-08-08 11:27:57 -07001261
Jeff Sharkey275e0852014-06-17 18:18:49 -07001262 if (pkg.mCertificates == null) {
1263 pkg.mCertificates = entryCerts;
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001264 pkg.mSignatures = entrySignatures;
dcashman55b10782014-04-09 14:20:38 -07001265 pkg.mSigningKeys = new ArraySet<PublicKey>();
1266 for (int i=0; i < entryCerts.length; i++) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001267 pkg.mSigningKeys.add(entryCerts[i][0].getPublicKey());
Kenny Rootbcc954d2011-08-08 16:19:08 -07001268 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001269 } else {
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001270 if (!Signature.areExactMatch(pkg.mSignatures, entrySignatures)) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001271 throw new PackageParserException(
1272 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, "Package " + apkPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001273 + " has mismatched certificates at entry "
Jeff Sharkey275e0852014-06-17 18:18:49 -07001274 + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001275 }
1276 }
1277 }
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001278 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeybc097552014-09-09 14:57:26 -07001279 } catch (GeneralSecurityException e) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001280 throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING,
1281 "Failed to collect certificates from " + apkPath, e);
Jeff Sharkeybc097552014-09-09 14:57:26 -07001282 } catch (IOException | RuntimeException e) {
1283 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1284 "Failed to collect certificates from " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001285 } finally {
1286 closeQuietly(jarFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288 }
1289
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001290 private static Signature[] convertToSignatures(Certificate[][] certs)
1291 throws CertificateEncodingException {
1292 final Signature[] res = new Signature[certs.length];
1293 for (int i = 0; i < certs.length; i++) {
1294 res[i] = new Signature(certs[i]);
1295 }
1296 return res;
1297 }
1298
Jeff Sharkey275e0852014-06-17 18:18:49 -07001299 /**
1300 * Utility method that retrieves lightweight details about a single APK
1301 * file, including package name, split name, and install location.
1302 *
1303 * @param apkFile path to a single APK
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001304 * @param flags optional parse flags, such as
1305 * {@link #PARSE_COLLECT_CERTIFICATES}
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001306 */
Jeff Sharkey275e0852014-06-17 18:18:49 -07001307 public static ApkLite parseApkLite(File apkFile, int flags)
1308 throws PackageParserException {
1309 final String apkPath = apkFile.getAbsolutePath();
1310
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001311 AssetManager assets = null;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001312 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001313 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001314 assets = new AssetManager();
1315 assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08001316 Build.VERSION.RESOURCES_SDK_INT);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001317
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001318 int cookie = assets.addAssetPath(apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001319 if (cookie == 0) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001320 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1321 "Failed to parse " + apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001322 }
1323
Kenny Root05ca4c92011-09-15 10:36:25 -07001324 final DisplayMetrics metrics = new DisplayMetrics();
1325 metrics.setToDefaults();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001326
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001327 final Resources res = new Resources(assets, metrics, null);
1328 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Kenny Root05ca4c92011-09-15 10:36:25 -07001329
Jeff Sharkey275e0852014-06-17 18:18:49 -07001330 final Signature[] signatures;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001331 final Certificate[][] certificates;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001332 if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
1333 // TODO: factor signature related items out of Package object
1334 final Package tempPkg = new Package(null);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001335 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1336 try {
Todd Kennedyf720a9d2016-04-15 09:44:36 -07001337 collectCertificates(tempPkg, apkFile, 0 /*parseFlags*/);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001338 } finally {
1339 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1340 }
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001341 signatures = tempPkg.mSignatures;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001342 certificates = tempPkg.mCertificates;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001343 } else {
1344 signatures = null;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001345 certificates = null;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001346 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001347
Jeff Sharkey275e0852014-06-17 18:18:49 -07001348 final AttributeSet attrs = parser;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001349 return parseApkLite(apkPath, res, parser, attrs, flags, signatures, certificates);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001350
1351 } catch (XmlPullParserException | IOException | RuntimeException e) {
1352 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1353 "Failed to parse " + apkPath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001354 } finally {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001355 IoUtils.closeQuietly(parser);
1356 IoUtils.closeQuietly(assets);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 }
1359
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001360 private static String validateName(String name, boolean requireSeparator,
1361 boolean requireFilename) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362 final int N = name.length();
1363 boolean hasSep = false;
1364 boolean front = true;
1365 for (int i=0; i<N; i++) {
1366 final char c = name.charAt(i);
1367 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1368 front = false;
1369 continue;
1370 }
1371 if (!front) {
1372 if ((c >= '0' && c <= '9') || c == '_') {
1373 continue;
1374 }
1375 }
1376 if (c == '.') {
1377 hasSep = true;
1378 front = true;
1379 continue;
1380 }
1381 return "bad character '" + c + "'";
1382 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001383 if (requireFilename && !FileUtils.isValidExtFilename(name)) {
1384 return "Invalid filename";
1385 }
1386 return hasSep || !requireSeparator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001387 ? null : "must have at least one '.' separator";
1388 }
1389
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001390 private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
Svet Ganov354cd3c2015-12-17 11:35:04 -08001391 AttributeSet attrs) throws IOException, XmlPullParserException,
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001392 PackageParserException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393
1394 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001395 while ((type = parser.next()) != XmlPullParser.START_TAG
1396 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 }
1398
Kenny Rootd2d29252011-08-08 11:27:57 -07001399 if (type != XmlPullParser.START_TAG) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001400 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1401 "No start tag found");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001403 if (!parser.getName().equals(TAG_MANIFEST)) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001404 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1405 "No <manifest> tag");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 }
1407
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001408 final String packageName = attrs.getAttributeValue(null, "package");
1409 if (!"android".equals(packageName)) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001410 final String error = validateName(packageName, true, true);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001411 if (error != null) {
1412 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1413 "Invalid manifest package: " + error);
1414 }
1415 }
1416
Jeff Sharkey275e0852014-06-17 18:18:49 -07001417 String splitName = attrs.getAttributeValue(null, "split");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001418 if (splitName != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001419 if (splitName.length() == 0) {
1420 splitName = null;
1421 } else {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001422 final String error = validateName(splitName, false, false);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001423 if (error != null) {
1424 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1425 "Invalid manifest split: " + error);
1426 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001427 }
1428 }
1429
1430 return Pair.create(packageName.intern(),
1431 (splitName != null) ? splitName.intern() : splitName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001432 }
1433
Jeff Sharkeybe520fb2014-07-04 18:23:17 -07001434 private static ApkLite parseApkLite(String codePath, Resources res, XmlPullParser parser,
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001435 AttributeSet attrs, int flags, Signature[] signatures, Certificate[][] certificates)
1436 throws IOException, XmlPullParserException, PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001437 final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001438
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001439 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001440 int versionCode = 0;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001441 int revisionCode = 0;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001442 boolean coreApp = false;
Narayan Kamathff110bd2014-07-04 18:30:45 +01001443 boolean multiArch = false;
Selim Gurun2d291d82016-02-05 17:50:53 -08001444 boolean use32bitAbi = false;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001445 boolean extractNativeLibs = true;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001446
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001447 for (int i = 0; i < attrs.getAttributeCount(); i++) {
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001448 final String attr = attrs.getAttributeName(i);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001449 if (attr.equals("installLocation")) {
1450 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001451 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001452 } else if (attr.equals("versionCode")) {
1453 versionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001454 } else if (attr.equals("revisionCode")) {
1455 revisionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001456 } else if (attr.equals("coreApp")) {
1457 coreApp = attrs.getAttributeBooleanValue(i, false);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001458 }
1459 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001460
1461 // Only search the tree when the tag is directly below <manifest>
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001462 int type;
Kenny Root05ca4c92011-09-15 10:36:25 -07001463 final int searchDepth = parser.getDepth() + 1;
1464
1465 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
1466 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1467 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
1468 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1469 continue;
1470 }
1471
1472 if (parser.getDepth() == searchDepth && "package-verifier".equals(parser.getName())) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001473 final VerifierInfo verifier = parseVerifier(res, parser, attrs, flags);
Kenny Root05ca4c92011-09-15 10:36:25 -07001474 if (verifier != null) {
1475 verifiers.add(verifier);
1476 }
1477 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001478
1479 if (parser.getDepth() == searchDepth && "application".equals(parser.getName())) {
1480 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1481 final String attr = attrs.getAttributeName(i);
1482 if ("multiArch".equals(attr)) {
1483 multiArch = attrs.getAttributeBooleanValue(i, false);
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001484 }
Selim Gurun2d291d82016-02-05 17:50:53 -08001485 if ("use32bitAbi".equals(attr)) {
1486 use32bitAbi = attrs.getAttributeBooleanValue(i, false);
Tao Baic9a02372016-01-12 15:02:24 -08001487 }
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001488 if ("extractNativeLibs".equals(attr)) {
1489 extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
Narayan Kamatha8755a82014-07-15 12:26:35 +01001490 }
1491 }
1492 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001493 }
1494
Jeff Sharkeybe520fb2014-07-04 18:23:17 -07001495 return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode,
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001496 revisionCode, installLocation, verifiers, signatures, certificates, coreApp,
1497 multiArch, use32bitAbi, extractNativeLibs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001498 }
1499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 /**
1501 * Temporary.
1502 */
1503 static public Signature stringToSignature(String str) {
1504 final int N = str.length();
1505 byte[] sig = new byte[N];
1506 for (int i=0; i<N; i++) {
1507 sig[i] = (byte)str.charAt(i);
1508 }
1509 return new Signature(sig);
1510 }
1511
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001512 /**
Svet Ganov354cd3c2015-12-17 11:35:04 -08001513 * Parses a child package and adds it to the parent if successful. If you add
1514 * new tags that need to be supported by child packages make sure to add them
1515 * to {@link #CHILD_PACKAGE_TAGS}.
1516 *
1517 * @param parentPkg The parent that contains the child
1518 * @param res Resources against which to resolve values
1519 * @param parser Parser of the manifest
1520 * @param flags Flags about how to parse
1521 * @param outError Human readable error if parsing fails
1522 * @return True of parsing succeeded.
1523 *
1524 * @throws XmlPullParserException
1525 * @throws IOException
1526 */
1527 private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser,
1528 int flags, String[] outError) throws XmlPullParserException, IOException {
1529 // Let ppl not abuse this mechanism by limiting the packages per APK
1530 if (parentPkg.childPackages != null && parentPkg.childPackages.size() + 2
1531 > MAX_PACKAGES_PER_APK) {
1532 outError[0] = "Maximum number of packages per APK is: " + MAX_PACKAGES_PER_APK;
1533 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1534 return false;
1535 }
1536
1537 // Make sure we have a valid child package name
1538 String childPackageName = parser.getAttributeValue(null, "package");
1539 if (validateName(childPackageName, true, false) != null) {
1540 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1541 return false;
1542 }
1543
1544 // Child packages must be unique
1545 if (childPackageName.equals(parentPkg.packageName)) {
1546 String message = "Child package name cannot be equal to parent package name: "
1547 + parentPkg.packageName;
1548 Slog.w(TAG, message);
1549 outError[0] = message;
1550 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1551 return false;
1552 }
1553
1554 // Child packages must be unique
1555 if (parentPkg.hasChildPackage(childPackageName)) {
1556 String message = "Duplicate child package:" + childPackageName;
1557 Slog.w(TAG, message);
1558 outError[0] = message;
1559 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1560 return false;
1561 }
1562
1563 // Go ahead and parse the child
1564 Package childPkg = new Package(childPackageName);
1565
1566 // Child package inherits parent version code/name/target SDK
1567 childPkg.mVersionCode = parentPkg.mVersionCode;
1568 childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
1569 childPkg.mVersionName = parentPkg.mVersionName;
1570 childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
Todd Kennedy89d60182016-03-11 11:18:32 -08001571 childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001572
1573 childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
1574 if (childPkg == null) {
1575 // If we got null then error was set during child parsing
1576 return false;
1577 }
1578
1579 // Set the parent-child relation
1580 if (parentPkg.childPackages == null) {
1581 parentPkg.childPackages = new ArrayList<>();
1582 }
1583 parentPkg.childPackages.add(childPkg);
1584 childPkg.parentPackage = parentPkg;
1585
1586 return true;
1587 }
1588
1589 /**
1590 * Parse the manifest of a <em>base APK</em>. When adding new features you
1591 * need to consider whether they should be supported by split APKs and child
1592 * packages.
1593 *
1594 * @param res The resources from which to resolve values
1595 * @param parser The manifest parser
1596 * @param flags Flags how to parse
1597 * @param outError Human readable error message
1598 * @return Parsed package or null on error.
1599 *
1600 * @throws XmlPullParserException
1601 * @throws IOException
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001602 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001603 private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001604 String[] outError) throws XmlPullParserException, IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001605 final String splitName;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001606 final String pkgName;
1607
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001608 try {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001609 Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001610 pkgName = packageSplit.first;
1611 splitName = packageSplit.second;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001612
1613 if (!TextUtils.isEmpty(splitName)) {
1614 outError[0] = "Expected base APK, but found split " + splitName;
1615 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1616 return null;
1617 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001618 } catch (PackageParserException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1620 return null;
1621 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001622
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001623 final Package pkg = new Package(pkgName);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001624
Svet Ganov354cd3c2015-12-17 11:35:04 -08001625 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001626 com.android.internal.R.styleable.AndroidManifest);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001627
Dianne Hackborn8472e612014-01-23 17:57:20 -08001628 pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001630 pkg.baseRevisionCode = sa.getInteger(
1631 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001632 pkg.mVersionName = sa.getNonConfigurationString(
1633 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 if (pkg.mVersionName != null) {
1635 pkg.mVersionName = pkg.mVersionName.intern();
1636 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001637
1638 pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
1639
1640 sa.recycle();
1641
1642 return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
1643 }
1644
1645 /**
1646 * This is the common parsing routing for handling parent and child
1647 * packages in a base APK. The difference between parent and child
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001648 * parsing is that some tags are not supported by child packages as
Svet Ganov354cd3c2015-12-17 11:35:04 -08001649 * well as some manifest attributes are ignored. The implementation
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001650 * assumes the calling code has already handled the manifest tag if needed
Svet Ganov354cd3c2015-12-17 11:35:04 -08001651 * (this applies to the parent only).
1652 *
1653 * @param pkg The package which to populate
1654 * @param acceptedTags Which tags to handle, null to handle all
1655 * @param res Resources against which to resolve values
1656 * @param parser Parser of the manifest
1657 * @param flags Flags about how to parse
1658 * @param outError Human readable error if parsing fails
1659 * @return The package if parsing succeeded or null.
1660 *
1661 * @throws XmlPullParserException
1662 * @throws IOException
1663 */
1664 private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
1665 XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
1666 IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001667 mParseInstrumentationArgs = null;
1668 mParseActivityArgs = null;
1669 mParseServiceArgs = null;
1670 mParseProviderArgs = null;
1671
1672 int type;
1673 boolean foundApp = false;
1674
1675 TypedArray sa = res.obtainAttributes(parser,
1676 com.android.internal.R.styleable.AndroidManifest);
1677
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001678 String str = sa.getNonConfigurationString(
1679 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
1680 if (str != null && str.length() > 0) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001681 String nameError = validateName(str, true, false);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001682 if (nameError != null && !"android".equals(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 outError[0] = "<manifest> specifies bad sharedUserId name \""
1684 + str + "\": " + nameError;
1685 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
1686 return null;
1687 }
1688 pkg.mSharedUserId = str.intern();
1689 pkg.mSharedUserLabel = sa.getResourceId(
1690 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
1691 }
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -08001692
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08001693 pkg.installLocation = sa.getInteger(
1694 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001695 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -07001696 pkg.applicationInfo.installLocation = pkg.installLocation;
Kenny Root7cb9be22012-05-30 15:30:37 -07001697
Alan Viverettefd274a02014-03-27 15:39:15 -07001698
Kenny Root7cb9be22012-05-30 15:30:37 -07001699 /* Set the global "forward lock" flag */
1700 if ((flags & PARSE_FORWARD_LOCK) != 0) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08001701 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
Kenny Root7cb9be22012-05-30 15:30:37 -07001702 }
1703
1704 /* Set the global "on SD card" flag */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001705 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
Kenny Root7cb9be22012-05-30 15:30:37 -07001706 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
1707 }
1708
Svet Ganov2acf0632015-11-24 19:10:59 -08001709 if ((flags & PARSE_IS_EPHEMERAL) != 0) {
1710 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_EPHEMERAL;
1711 }
1712
Dianne Hackborn723738c2009-06-25 19:48:04 -07001713 // Resource boolean are -1, so 1 means we don't know the value.
1714 int supportsSmallScreens = 1;
1715 int supportsNormalScreens = 1;
1716 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001717 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001718 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001719 int anyDensity = 1;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001720
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001721 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -07001722 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1723 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1724 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001725 continue;
1726 }
1727
1728 String tagName = parser.getName();
Svet Ganov354cd3c2015-12-17 11:35:04 -08001729
1730 if (acceptedTags != null && !acceptedTags.contains(tagName)) {
1731 Slog.w(TAG, "Skipping unsupported element under <manifest>: "
1732 + tagName + " at " + mArchiveSourcePath + " "
1733 + parser.getPositionDescription());
1734 XmlUtils.skipCurrentTag(parser);
1735 continue;
1736 }
1737
1738 if (tagName.equals(TAG_APPLICATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 if (foundApp) {
1740 if (RIGID_PARSER) {
1741 outError[0] = "<manifest> has more than one <application>";
1742 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1743 return null;
1744 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07001745 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746 XmlUtils.skipCurrentTag(parser);
1747 continue;
1748 }
1749 }
1750
1751 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001752 if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 return null;
1754 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001755 } else if (tagName.equals(TAG_OVERLAY)) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001756 sa = res.obtainAttributes(parser,
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01001757 com.android.internal.R.styleable.AndroidManifestResourceOverlay);
1758 pkg.mOverlayTarget = sa.getString(
1759 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
1760 pkg.mOverlayPriority = sa.getInt(
1761 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
1762 -1);
1763 sa.recycle();
1764
1765 if (pkg.mOverlayTarget == null) {
1766 outError[0] = "<overlay> does not specify a target package";
1767 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1768 return null;
1769 }
1770 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
1771 outError[0] = "<overlay> priority must be between 0 and 9999";
1772 mParseError =
1773 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1774 return null;
1775 }
1776 XmlUtils.skipCurrentTag(parser);
1777
Svet Ganov354cd3c2015-12-17 11:35:04 -08001778 } else if (tagName.equals(TAG_KEY_SETS)) {
1779 if (!parseKeySets(pkg, res, parser, outError)) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08001780 return null;
1781 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001782 } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
1783 if (parsePermissionGroup(pkg, flags, res, parser, outError) == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 return null;
1785 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001786 } else if (tagName.equals(TAG_PERMISSION)) {
1787 if (parsePermission(pkg, res, parser, outError) == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001788 return null;
1789 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001790 } else if (tagName.equals(TAG_PERMISSION_TREE)) {
1791 if (parsePermissionTree(pkg, res, parser, outError) == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 return null;
1793 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001794 } else if (tagName.equals(TAG_USES_PERMISSION)) {
1795 if (!parseUsesPermission(pkg, res, parser)) {
Svetoslav96a77162015-04-03 13:58:33 -07001796 return null;
1797 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001798 } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
1799 || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
1800 if (!parseUsesPermission(pkg, res, parser)) {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07001801 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001802 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001803 } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804 ConfigurationInfo cPref = new ConfigurationInfo();
Svet Ganov354cd3c2015-12-17 11:35:04 -08001805 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001806 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
1807 cPref.reqTouchScreen = sa.getInt(
1808 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
1809 Configuration.TOUCHSCREEN_UNDEFINED);
1810 cPref.reqKeyboardType = sa.getInt(
1811 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
1812 Configuration.KEYBOARD_UNDEFINED);
1813 if (sa.getBoolean(
1814 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
1815 false)) {
1816 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
1817 }
1818 cPref.reqNavigation = sa.getInt(
1819 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
1820 Configuration.NAVIGATION_UNDEFINED);
1821 if (sa.getBoolean(
1822 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
1823 false)) {
1824 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
1825 }
1826 sa.recycle();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001827 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001828
1829 XmlUtils.skipCurrentTag(parser);
1830
Svet Ganov354cd3c2015-12-17 11:35:04 -08001831 } else if (tagName.equals(TAG_USES_FEATURE)) {
1832 FeatureInfo fi = parseUsesFeature(res, parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001833 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
1834
Dianne Hackborn49237342009-08-27 20:08:01 -07001835 if (fi.name == null) {
1836 ConfigurationInfo cPref = new ConfigurationInfo();
1837 cPref.reqGlEsVersion = fi.reqGlEsVersion;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001838 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
Dianne Hackborn49237342009-08-27 20:08:01 -07001839 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07001840
1841 XmlUtils.skipCurrentTag(parser);
1842
Svet Ganov354cd3c2015-12-17 11:35:04 -08001843 } else if (tagName.equals(TAG_FEATURE_GROUP)) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07001844 FeatureGroupInfo group = new FeatureGroupInfo();
1845 ArrayList<FeatureInfo> features = null;
1846 final int innerDepth = parser.getDepth();
1847 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1848 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
1849 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1850 continue;
1851 }
Adam Lesinski2c72b682014-06-24 09:56:01 -07001852
Adam Lesinskid3edfde2014-08-08 17:32:44 -07001853 final String innerTagName = parser.getName();
1854 if (innerTagName.equals("uses-feature")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001855 FeatureInfo featureInfo = parseUsesFeature(res, parser);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07001856 // FeatureGroups are stricter and mandate that
1857 // any <uses-feature> declared are mandatory.
1858 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
1859 features = ArrayUtils.add(features, featureInfo);
1860 } else {
1861 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
1862 " at " + mArchiveSourcePath + " " +
1863 parser.getPositionDescription());
1864 }
1865 XmlUtils.skipCurrentTag(parser);
1866 }
1867
1868 if (features != null) {
1869 group.features = new FeatureInfo[features.size()];
1870 group.features = features.toArray(group.features);
1871 }
1872 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
Adam Lesinski2c72b682014-06-24 09:56:01 -07001873
Svet Ganov354cd3c2015-12-17 11:35:04 -08001874 } else if (tagName.equals(TAG_USES_SDK)) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001875 if (SDK_VERSION > 0) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001876 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001877 com.android.internal.R.styleable.AndroidManifestUsesSdk);
1878
Todd Kennedy4f657082016-06-28 10:31:05 -07001879 int minVers = 1;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001880 String minCode = null;
1881 int targetVers = 0;
1882 String targetCode = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001883
Dianne Hackborn851a5412009-05-08 12:06:44 -07001884 TypedValue val = sa.peekValue(
1885 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
1886 if (val != null) {
1887 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
1888 targetCode = minCode = val.string.toString();
1889 } else {
1890 // If it's not a string, it's an integer.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001891 targetVers = minVers = val.data;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001892 }
1893 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001894
Dianne Hackborn851a5412009-05-08 12:06:44 -07001895 val = sa.peekValue(
1896 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
1897 if (val != null) {
1898 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
Todd Kennedy89d60182016-03-11 11:18:32 -08001899 targetCode = val.string.toString();
1900 if (minCode == null) {
1901 minCode = targetCode;
1902 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07001903 } else {
1904 // If it's not a string, it's an integer.
1905 targetVers = val.data;
1906 }
1907 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001908
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001909 sa.recycle();
1910
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001911 if (minCode != null) {
Dianne Hackbornffcda102014-04-24 13:06:27 -07001912 boolean allowedCodename = false;
1913 for (String codename : SDK_CODENAMES) {
1914 if (minCode.equals(codename)) {
1915 allowedCodename = true;
1916 break;
1917 }
1918 }
1919 if (!allowedCodename) {
1920 if (SDK_CODENAMES.length > 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001921 outError[0] = "Requires development platform " + minCode
Dianne Hackbornffcda102014-04-24 13:06:27 -07001922 + " (current platform is any of "
1923 + Arrays.toString(SDK_CODENAMES) + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001924 } else {
1925 outError[0] = "Requires development platform " + minCode
1926 + " but this is a release platform.";
1927 }
1928 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1929 return null;
1930 }
Todd Kennedy6e2e7f52016-05-02 14:56:45 -07001931 pkg.applicationInfo.minSdkVersion =
1932 android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001933 } else if (minVers > SDK_VERSION) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001934 outError[0] = "Requires newer sdk version #" + minVers
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001935 + " (current version is #" + SDK_VERSION + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001936 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1937 return null;
Todd Kennedy89d60182016-03-11 11:18:32 -08001938 } else {
Todd Kennedy6e2e7f52016-05-02 14:56:45 -07001939 pkg.applicationInfo.minSdkVersion = minVers;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001940 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001941
Dianne Hackborn851a5412009-05-08 12:06:44 -07001942 if (targetCode != null) {
Dianne Hackbornffcda102014-04-24 13:06:27 -07001943 boolean allowedCodename = false;
1944 for (String codename : SDK_CODENAMES) {
1945 if (targetCode.equals(codename)) {
1946 allowedCodename = true;
1947 break;
1948 }
1949 }
1950 if (!allowedCodename) {
1951 if (SDK_CODENAMES.length > 0) {
Dianne Hackborn851a5412009-05-08 12:06:44 -07001952 outError[0] = "Requires development platform " + targetCode
Dianne Hackbornffcda102014-04-24 13:06:27 -07001953 + " (current platform is any of "
1954 + Arrays.toString(SDK_CODENAMES) + ")";
Dianne Hackborn851a5412009-05-08 12:06:44 -07001955 } else {
1956 outError[0] = "Requires development platform " + targetCode
1957 + " but this is a release platform.";
1958 }
1959 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1960 return null;
1961 }
1962 // If the code matches, it definitely targets this SDK.
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001963 pkg.applicationInfo.targetSdkVersion
1964 = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
1965 } else {
1966 pkg.applicationInfo.targetSdkVersion = targetVers;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001967 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001968 }
1969
1970 XmlUtils.skipCurrentTag(parser);
1971
Svet Ganov354cd3c2015-12-17 11:35:04 -08001972 } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
1973 sa = res.obtainAttributes(parser,
Dianne Hackborn723738c2009-06-25 19:48:04 -07001974 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
1975
Dianne Hackborndf6e9802011-05-26 14:20:23 -07001976 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
1977 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
1978 0);
1979 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
1980 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
1981 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07001982 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
1983 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
1984 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07001985
Dianne Hackborn723738c2009-06-25 19:48:04 -07001986 // This is a trick to get a boolean and still able to detect
1987 // if a value was actually set.
1988 supportsSmallScreens = sa.getInteger(
1989 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
1990 supportsSmallScreens);
1991 supportsNormalScreens = sa.getInteger(
1992 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
1993 supportsNormalScreens);
1994 supportsLargeScreens = sa.getInteger(
1995 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
1996 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001997 supportsXLargeScreens = sa.getInteger(
1998 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
1999 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002000 resizeable = sa.getInteger(
2001 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002002 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002003 anyDensity = sa.getInteger(
2004 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
2005 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07002006
2007 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002008
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07002009 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002010
Svet Ganov354cd3c2015-12-17 11:35:04 -08002011 } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
2012 sa = res.obtainAttributes(parser,
Dianne Hackborn854060af2009-07-09 18:14:31 -07002013 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
2014
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002015 // Note: don't allow this value to be a reference to a resource
2016 // that may change.
Dianne Hackborn854060af2009-07-09 18:14:31 -07002017 String name = sa.getNonResourceString(
2018 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
2019
2020 sa.recycle();
2021
2022 if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
2023 if (pkg.protectedBroadcasts == null) {
2024 pkg.protectedBroadcasts = new ArrayList<String>();
2025 }
2026 if (!pkg.protectedBroadcasts.contains(name)) {
2027 pkg.protectedBroadcasts.add(name.intern());
2028 }
2029 }
2030
2031 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002032
Svet Ganov354cd3c2015-12-17 11:35:04 -08002033 } else if (tagName.equals(TAG_INSTRUMENTATION)) {
2034 if (parseInstrumentation(pkg, res, parser, outError) == null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002035 return null;
2036 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002037 } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
2038 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002039 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2040
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002041 String orig =sa.getNonConfigurationString(
2042 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002043 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002044 if (pkg.mOriginalPackages == null) {
2045 pkg.mOriginalPackages = new ArrayList<String>();
2046 pkg.mRealPackage = pkg.packageName;
2047 }
2048 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002049 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002050
2051 sa.recycle();
2052
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002053 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002054
Svet Ganov354cd3c2015-12-17 11:35:04 -08002055 } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
2056 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002057 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2058
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002059 String name = sa.getNonConfigurationString(
2060 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002061
2062 sa.recycle();
2063
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002064 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002065 if (pkg.mAdoptPermissions == null) {
2066 pkg.mAdoptPermissions = new ArrayList<String>();
2067 }
2068 pkg.mAdoptPermissions.add(name);
2069 }
2070
2071 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002072
Svet Ganov354cd3c2015-12-17 11:35:04 -08002073 } else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002074 // Just skip this tag
2075 XmlUtils.skipCurrentTag(parser);
2076 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002077
Svet Ganov354cd3c2015-12-17 11:35:04 -08002078 } else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002079 // Just skip this tag
2080 XmlUtils.skipCurrentTag(parser);
2081 continue;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002082 } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
Michael Wrighteaeb1902013-09-05 18:15:57 -07002083 XmlUtils.skipCurrentTag(parser);
2084 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002085
Svet Ganov354cd3c2015-12-17 11:35:04 -08002086 } else if (tagName.equals(TAG_EAT_COMMENT)) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002087 // Just skip this tag
2088 XmlUtils.skipCurrentTag(parser);
2089 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002090
Svet Ganov354cd3c2015-12-17 11:35:04 -08002091 } else if (tagName.equals(TAG_PACKAGE)) {
Svet Ganova7532cf2016-05-02 08:13:17 -07002092 if (!MULTI_PACKAGE_APK_ENABLED) {
2093 XmlUtils.skipCurrentTag(parser);
2094 continue;
2095 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002096 if (!parseBaseApkChild(pkg, res, parser, flags, outError)) {
2097 // If parsing a child failed the error is already set
2098 return null;
2099 }
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002100
2101 } else if (tagName.equals(TAG_RESTRICT_UPDATE)) {
2102 if ((flags & PARSE_IS_SYSTEM_DIR) != 0) {
2103 sa = res.obtainAttributes(parser,
2104 com.android.internal.R.styleable.AndroidManifestRestrictUpdate);
2105 final String hash = sa.getNonConfigurationString(
2106 com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0);
2107 sa.recycle();
2108
2109 pkg.restrictUpdateHash = null;
2110 if (hash != null) {
2111 final int hashLength = hash.length();
2112 final byte[] hashBytes = new byte[hashLength / 2];
2113 for (int i = 0; i < hashLength; i += 2){
2114 hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4)
2115 + Character.digit(hash.charAt(i + 1), 16));
2116 }
2117 pkg.restrictUpdateHash = hashBytes;
2118 }
2119 }
2120
2121 XmlUtils.skipCurrentTag(parser);
2122
Dianne Hackborn854060af2009-07-09 18:14:31 -07002123 } else if (RIGID_PARSER) {
2124 outError[0] = "Bad element under <manifest>: "
2125 + parser.getName();
2126 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2127 return null;
2128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002129 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002130 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002131 + " at " + mArchiveSourcePath + " "
2132 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002133 XmlUtils.skipCurrentTag(parser);
2134 continue;
2135 }
2136 }
2137
2138 if (!foundApp && pkg.instrumentation.size() == 0) {
2139 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
2140 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
2141 }
2142
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002143 final int NP = PackageParser.NEW_PERMISSIONS.length;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002144 StringBuilder implicitPerms = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002145 for (int ip=0; ip<NP; ip++) {
2146 final PackageParser.NewPermissionInfo npi
2147 = PackageParser.NEW_PERMISSIONS[ip];
2148 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
2149 break;
2150 }
2151 if (!pkg.requestedPermissions.contains(npi.name)) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002152 if (implicitPerms == null) {
2153 implicitPerms = new StringBuilder(128);
2154 implicitPerms.append(pkg.packageName);
2155 implicitPerms.append(": compat added ");
2156 } else {
2157 implicitPerms.append(' ');
2158 }
2159 implicitPerms.append(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002160 pkg.requestedPermissions.add(npi.name);
2161 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002162 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002163 if (implicitPerms != null) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002164 Slog.i(TAG, implicitPerms.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002165 }
Dianne Hackborn79245122012-03-12 10:51:26 -07002166
2167 final int NS = PackageParser.SPLIT_PERMISSIONS.length;
2168 for (int is=0; is<NS; is++) {
2169 final PackageParser.SplitPermissionInfo spi
2170 = PackageParser.SPLIT_PERMISSIONS[is];
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -07002171 if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
2172 || !pkg.requestedPermissions.contains(spi.rootPerm)) {
Dianne Hackborn5e4705a2012-04-06 12:55:53 -07002173 continue;
Dianne Hackborn79245122012-03-12 10:51:26 -07002174 }
2175 for (int in=0; in<spi.newPerms.length; in++) {
2176 final String perm = spi.newPerms[in];
2177 if (!pkg.requestedPermissions.contains(perm)) {
2178 pkg.requestedPermissions.add(perm);
Dianne Hackborn79245122012-03-12 10:51:26 -07002179 }
2180 }
2181 }
2182
Dianne Hackborn723738c2009-06-25 19:48:04 -07002183 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
2184 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002185 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002186 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
2187 }
2188 if (supportsNormalScreens != 0) {
2189 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
2190 }
2191 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
2192 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002193 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002194 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
2195 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002196 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
2197 && pkg.applicationInfo.targetSdkVersion
2198 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
2199 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
2200 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002201 if (resizeable < 0 || (resizeable > 0
2202 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002203 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002204 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
2205 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002206 if (anyDensity < 0 || (anyDensity > 0
2207 && pkg.applicationInfo.targetSdkVersion
2208 >= android.os.Build.VERSION_CODES.DONUT)) {
2209 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07002210 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07002211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002212 return pkg;
2213 }
2214
Todd Kennedy27c24fb2015-09-17 16:49:25 -07002215 private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002216 FeatureInfo fi = new FeatureInfo();
2217 TypedArray sa = res.obtainAttributes(attrs,
2218 com.android.internal.R.styleable.AndroidManifestUsesFeature);
2219 // Note: don't allow this value to be a reference to a resource
2220 // that may change.
2221 fi.name = sa.getNonResourceString(
2222 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
Jeff Sharkey115d2c12016-02-15 17:25:57 -07002223 fi.version = sa.getInt(
2224 com.android.internal.R.styleable.AndroidManifestUsesFeature_version, 0);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002225 if (fi.name == null) {
2226 fi.reqGlEsVersion = sa.getInt(
2227 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
2228 FeatureInfo.GL_ES_VERSION_UNDEFINED);
2229 }
2230 if (sa.getBoolean(
2231 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) {
2232 fi.flags |= FeatureInfo.FLAG_REQUIRED;
2233 }
2234 sa.recycle();
2235 return fi;
2236 }
2237
Svet Ganov354cd3c2015-12-17 11:35:04 -08002238 private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
2239 throws XmlPullParserException, IOException {
2240 TypedArray sa = res.obtainAttributes(parser,
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002241 com.android.internal.R.styleable.AndroidManifestUsesPermission);
2242
2243 // Note: don't allow this value to be a reference to a resource
2244 // that may change.
2245 String name = sa.getNonResourceString(
2246 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002247
Christopher Tatefb0676a2013-09-16 16:34:52 -07002248 int maxSdkVersion = 0;
2249 TypedValue val = sa.peekValue(
2250 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
2251 if (val != null) {
2252 if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
2253 maxSdkVersion = val.data;
2254 }
2255 }
2256
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002257 sa.recycle();
2258
Christopher Tatefb0676a2013-09-16 16:34:52 -07002259 if ((maxSdkVersion == 0) || (maxSdkVersion >= Build.VERSION.RESOURCES_SDK_INT)) {
2260 if (name != null) {
2261 int index = pkg.requestedPermissions.indexOf(name);
2262 if (index == -1) {
2263 pkg.requestedPermissions.add(name.intern());
Christopher Tatefb0676a2013-09-16 16:34:52 -07002264 } else {
Svetoslav96a77162015-04-03 13:58:33 -07002265 Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
2266 + name + " in package: " + pkg.packageName + " at: "
2267 + parser.getPositionDescription());
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002268 }
2269 }
2270 }
2271
2272 XmlUtils.skipCurrentTag(parser);
2273 return true;
2274 }
2275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002276 private static String buildClassName(String pkg, CharSequence clsSeq,
2277 String[] outError) {
2278 if (clsSeq == null || clsSeq.length() <= 0) {
2279 outError[0] = "Empty class name in package " + pkg;
2280 return null;
2281 }
2282 String cls = clsSeq.toString();
2283 char c = cls.charAt(0);
2284 if (c == '.') {
2285 return (pkg + cls).intern();
2286 }
2287 if (cls.indexOf('.') < 0) {
2288 StringBuilder b = new StringBuilder(pkg);
2289 b.append('.');
2290 b.append(cls);
2291 return b.toString().intern();
2292 }
Todd Kennedyafb52692016-08-22 15:44:00 -07002293 return cls.intern();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002294 }
2295
2296 private static String buildCompoundName(String pkg,
2297 CharSequence procSeq, String type, String[] outError) {
2298 String proc = procSeq.toString();
2299 char c = proc.charAt(0);
2300 if (pkg != null && c == ':') {
2301 if (proc.length() < 2) {
2302 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
2303 + ": must be at least two characters";
2304 return null;
2305 }
2306 String subName = proc.substring(1);
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002307 String nameError = validateName(subName, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002308 if (nameError != null) {
2309 outError[0] = "Invalid " + type + " name " + proc + " in package "
2310 + pkg + ": " + nameError;
2311 return null;
2312 }
2313 return (pkg + proc).intern();
2314 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002315 String nameError = validateName(proc, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002316 if (nameError != null && !"system".equals(proc)) {
2317 outError[0] = "Invalid " + type + " name " + proc + " in package "
2318 + pkg + ": " + nameError;
2319 return null;
2320 }
2321 return proc.intern();
2322 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002324 private static String buildProcessName(String pkg, String defProc,
2325 CharSequence procSeq, int flags, String[] separateProcesses,
2326 String[] outError) {
2327 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
2328 return defProc != null ? defProc : pkg;
2329 }
2330 if (separateProcesses != null) {
2331 for (int i=separateProcesses.length-1; i>=0; i--) {
2332 String sp = separateProcesses[i];
2333 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
2334 return pkg;
2335 }
2336 }
2337 }
2338 if (procSeq == null || procSeq.length() <= 0) {
2339 return defProc;
2340 }
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002341 return buildCompoundName(pkg, procSeq, "process", outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002342 }
2343
2344 private static String buildTaskAffinityName(String pkg, String defProc,
2345 CharSequence procSeq, String[] outError) {
2346 if (procSeq == null) {
2347 return defProc;
2348 }
2349 if (procSeq.length() <= 0) {
2350 return null;
2351 }
2352 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
2353 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002354
dcashman989eb3712014-06-17 12:56:12 -07002355 private boolean parseKeySets(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002356 XmlResourceParser parser, String[] outError)
Geremy Condraf1bcca82013-01-07 22:35:24 -08002357 throws XmlPullParserException, IOException {
dcashman989eb3712014-06-17 12:56:12 -07002358 // we've encountered the 'key-sets' tag
Geremy Condraf1bcca82013-01-07 22:35:24 -08002359 // all the keys and keysets that we want must be defined here
2360 // so we're going to iterate over the parser and pull out the things we want
2361 int outerDepth = parser.getDepth();
dcashman989eb3712014-06-17 12:56:12 -07002362 int currentKeySetDepth = -1;
Geremy Condraf1bcca82013-01-07 22:35:24 -08002363 int type;
dcashman989eb3712014-06-17 12:56:12 -07002364 String currentKeySet = null;
2365 ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
2366 ArraySet<String> upgradeKeySets = new ArraySet<String>();
2367 ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
2368 ArraySet<String> improperKeySets = new ArraySet<String>();
Geremy Condraf1bcca82013-01-07 22:35:24 -08002369 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2370 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2371 if (type == XmlPullParser.END_TAG) {
dcashman989eb3712014-06-17 12:56:12 -07002372 if (parser.getDepth() == currentKeySetDepth) {
2373 currentKeySet = null;
2374 currentKeySetDepth = -1;
Kenny Root37dca152013-07-10 14:01:49 -07002375 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002376 continue;
2377 }
dcashman989eb3712014-06-17 12:56:12 -07002378 String tagName = parser.getName();
2379 if (tagName.equals("key-set")) {
2380 if (currentKeySet != null) {
dcashman5db0cd42015-05-22 15:24:40 -07002381 outError[0] = "Improperly nested 'key-set' tag at "
2382 + parser.getPositionDescription();
2383 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002384 return false;
2385 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002386 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002387 com.android.internal.R.styleable.AndroidManifestKeySet);
2388 final String keysetName = sa.getNonResourceString(
2389 com.android.internal.R.styleable.AndroidManifestKeySet_name);
2390 definedKeySets.put(keysetName, new ArraySet<String>());
2391 currentKeySet = keysetName;
2392 currentKeySetDepth = parser.getDepth();
2393 sa.recycle();
2394 } else if (tagName.equals("public-key")) {
2395 if (currentKeySet == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002396 outError[0] = "Improperly nested 'key-set' tag at "
2397 + parser.getPositionDescription();
2398 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002399 return false;
2400 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002401 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002402 com.android.internal.R.styleable.AndroidManifestPublicKey);
2403 final String publicKeyName = sa.getNonResourceString(
2404 com.android.internal.R.styleable.AndroidManifestPublicKey_name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002405 final String encodedKey = sa.getNonResourceString(
dcashman989eb3712014-06-17 12:56:12 -07002406 com.android.internal.R.styleable.AndroidManifestPublicKey_value);
2407 if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002408 outError[0] = "'public-key' " + publicKeyName + " must define a public-key value"
2409 + " on first use at " + parser.getPositionDescription();
2410 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Kenny Root37dca152013-07-10 14:01:49 -07002411 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002412 return false;
2413 } else if (encodedKey != null) {
2414 PublicKey currentKey = parsePublicKey(encodedKey);
2415 if (currentKey == null) {
2416 Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
2417 + parser.getPositionDescription() + " key-set " + currentKeySet
2418 + " will not be added to the package's defined key-sets.");
2419 sa.recycle();
2420 improperKeySets.add(currentKeySet);
2421 XmlUtils.skipCurrentTag(parser);
2422 continue;
2423 }
2424 if (publicKeys.get(publicKeyName) == null
2425 || publicKeys.get(publicKeyName).equals(currentKey)) {
2426
2427 /* public-key first definition, or matches old definition */
2428 publicKeys.put(publicKeyName, currentKey);
2429 } else {
dcashman5db0cd42015-05-22 15:24:40 -07002430 outError[0] = "Value of 'public-key' " + publicKeyName
dcashman989eb3712014-06-17 12:56:12 -07002431 + " conflicts with previously defined value at "
dcashman5db0cd42015-05-22 15:24:40 -07002432 + parser.getPositionDescription();
2433 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002434 sa.recycle();
2435 return false;
2436 }
Kenny Root37dca152013-07-10 14:01:49 -07002437 }
dcashman989eb3712014-06-17 12:56:12 -07002438 definedKeySets.get(currentKeySet).add(publicKeyName);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002439 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002440 XmlUtils.skipCurrentTag(parser);
2441 } else if (tagName.equals("upgrade-key-set")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002442 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002443 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
2444 String name = sa.getNonResourceString(
2445 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
2446 upgradeKeySets.add(name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002447 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002448 XmlUtils.skipCurrentTag(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002449 } else if (RIGID_PARSER) {
dcashman5db0cd42015-05-22 15:24:40 -07002450 outError[0] = "Bad element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08002451 + " at " + mArchiveSourcePath + " "
dcashman5db0cd42015-05-22 15:24:40 -07002452 + parser.getPositionDescription();
2453 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Geremy Condraf1bcca82013-01-07 22:35:24 -08002454 return false;
2455 } else {
dcashman989eb3712014-06-17 12:56:12 -07002456 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08002457 + " at " + mArchiveSourcePath + " "
2458 + parser.getPositionDescription());
2459 XmlUtils.skipCurrentTag(parser);
2460 continue;
2461 }
2462 }
dcashman989eb3712014-06-17 12:56:12 -07002463 Set<String> publicKeyNames = publicKeys.keySet();
2464 if (publicKeyNames.removeAll(definedKeySets.keySet())) {
dcashman5db0cd42015-05-22 15:24:40 -07002465 outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
2466 + "'key-set' and 'public-key' names must be distinct.";
2467 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002468 return false;
2469 }
2470 owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
2471 for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) {
2472 final String keySetName = e.getKey();
2473 if (e.getValue().size() == 0) {
2474 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
2475 + "'key-set' " + keySetName + " has no valid associated 'public-key'."
2476 + " Not including in package's defined key-sets.");
2477 continue;
2478 } else if (improperKeySets.contains(keySetName)) {
2479 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
2480 + "'key-set' " + keySetName + " contained improper 'public-key'"
2481 + " tags. Not including in package's defined key-sets.");
2482 continue;
2483 }
2484 owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
2485 for (String s : e.getValue()) {
2486 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
Geremy Condraf1bcca82013-01-07 22:35:24 -08002487 }
2488 }
dcashman989eb3712014-06-17 12:56:12 -07002489 if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
2490 owner.mUpgradeKeySets = upgradeKeySets;
2491 } else {
dcashman5db0cd42015-05-22 15:24:40 -07002492 outError[0] ="Package" + owner.packageName + " AndroidManifext.xml "
2493 + "does not define all 'upgrade-key-set's .";
2494 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002495 return false;
2496 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002497 return true;
2498 }
2499
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07002500 private PermissionGroup parsePermissionGroup(Package owner, int flags, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002501 XmlResourceParser parser, String[] outError)
2502 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002503 PermissionGroup perm = new PermissionGroup(owner);
2504
Svet Ganov354cd3c2015-12-17 11:35:04 -08002505 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002506 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002507 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07002508 "<permission-group>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002509 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
2510 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002511 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07002512 com.android.internal.R.styleable.AndroidManifestPermissionGroup_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08002513 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
2514 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002515 sa.recycle();
2516 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2517 return null;
2518 }
2519
2520 perm.info.descriptionRes = sa.getResourceId(
2521 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
2522 0);
Dianne Hackborn7454d3b2012-09-12 17:22:00 -07002523 perm.info.flags = sa.getInt(
2524 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07002525 perm.info.priority = sa.getInt(
2526 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
Dianne Hackborn99222d22012-05-06 16:30:15 -07002527 if (perm.info.priority > 0 && (flags&PARSE_IS_SYSTEM) == 0) {
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07002528 perm.info.priority = 0;
2529 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002530
2531 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002532
Svet Ganov354cd3c2015-12-17 11:35:04 -08002533 if (!parseAllMetaData(res, parser, "<permission-group>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002534 outError)) {
2535 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2536 return null;
2537 }
2538
2539 owner.permissionGroups.add(perm);
2540
2541 return perm;
2542 }
2543
2544 private Permission parsePermission(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002545 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002546 throws XmlPullParserException, IOException {
2547 Permission perm = new Permission(owner);
2548
Svet Ganov354cd3c2015-12-17 11:35:04 -08002549 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002550 com.android.internal.R.styleable.AndroidManifestPermission);
2551
2552 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07002553 "<permission>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002554 com.android.internal.R.styleable.AndroidManifestPermission_name,
2555 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002556 com.android.internal.R.styleable.AndroidManifestPermission_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07002557 com.android.internal.R.styleable.AndroidManifestPermission_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08002558 com.android.internal.R.styleable.AndroidManifestPermission_logo,
2559 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002560 sa.recycle();
2561 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2562 return null;
2563 }
2564
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002565 // Note: don't allow this value to be a reference to a resource
2566 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002567 perm.info.group = sa.getNonResourceString(
2568 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
2569 if (perm.info.group != null) {
2570 perm.info.group = perm.info.group.intern();
2571 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002572
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002573 perm.info.descriptionRes = sa.getResourceId(
2574 com.android.internal.R.styleable.AndroidManifestPermission_description,
2575 0);
2576
2577 perm.info.protectionLevel = sa.getInt(
2578 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
2579 PermissionInfo.PROTECTION_NORMAL);
2580
Dianne Hackborn2ca2c872012-09-16 16:03:36 -07002581 perm.info.flags = sa.getInt(
2582 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
2583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002584 sa.recycle();
Dianne Hackborne639da72012-02-21 15:11:13 -08002585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002586 if (perm.info.protectionLevel == -1) {
2587 outError[0] = "<permission> does not specify protectionLevel";
2588 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2589 return null;
2590 }
Dianne Hackborne639da72012-02-21 15:11:13 -08002591
2592 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
2593
2594 if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_FLAGS) != 0) {
2595 if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
2596 PermissionInfo.PROTECTION_SIGNATURE) {
2597 outError[0] = "<permission> protectionLevel specifies a flag but is "
2598 + "not based on signature type";
2599 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2600 return null;
2601 }
2602 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002603
Svet Ganov354cd3c2015-12-17 11:35:04 -08002604 if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002605 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2606 return null;
2607 }
2608
2609 owner.permissions.add(perm);
2610
2611 return perm;
2612 }
2613
2614 private Permission parsePermissionTree(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002615 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002616 throws XmlPullParserException, IOException {
2617 Permission perm = new Permission(owner);
2618
Svet Ganov354cd3c2015-12-17 11:35:04 -08002619 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002620 com.android.internal.R.styleable.AndroidManifestPermissionTree);
2621
2622 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07002623 "<permission-tree>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002624 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
2625 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002626 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07002627 com.android.internal.R.styleable.AndroidManifestPermissionTree_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08002628 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
2629 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002630 sa.recycle();
2631 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2632 return null;
2633 }
2634
2635 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002636
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002637 int index = perm.info.name.indexOf('.');
2638 if (index > 0) {
2639 index = perm.info.name.indexOf('.', index+1);
2640 }
2641 if (index < 0) {
2642 outError[0] = "<permission-tree> name has less than three segments: "
2643 + perm.info.name;
2644 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2645 return null;
2646 }
2647
2648 perm.info.descriptionRes = 0;
2649 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
2650 perm.tree = true;
2651
Svet Ganov354cd3c2015-12-17 11:35:04 -08002652 if (!parseAllMetaData(res, parser, "<permission-tree>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002653 outError)) {
2654 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2655 return null;
2656 }
2657
2658 owner.permissions.add(perm);
2659
2660 return perm;
2661 }
2662
2663 private Instrumentation parseInstrumentation(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002664 XmlResourceParser parser, String[] outError)
2665 throws XmlPullParserException, IOException {
2666 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002667 com.android.internal.R.styleable.AndroidManifestInstrumentation);
2668
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002669 if (mParseInstrumentationArgs == null) {
2670 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
2671 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
2672 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002673 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07002674 com.android.internal.R.styleable.AndroidManifestInstrumentation_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08002675 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
2676 com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002677 mParseInstrumentationArgs.tag = "<instrumentation>";
2678 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002679
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002680 mParseInstrumentationArgs.sa = sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002681
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002682 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
2683 new InstrumentationInfo());
2684 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002685 sa.recycle();
2686 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2687 return null;
2688 }
2689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002690 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002691 // Note: don't allow this value to be a reference to a resource
2692 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002693 str = sa.getNonResourceString(
2694 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
2695 a.info.targetPackage = str != null ? str.intern() : null;
2696
2697 a.info.handleProfiling = sa.getBoolean(
2698 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
2699 false);
2700
2701 a.info.functionalTest = sa.getBoolean(
2702 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
2703 false);
2704
2705 sa.recycle();
2706
2707 if (a.info.targetPackage == null) {
2708 outError[0] = "<instrumentation> does not specify targetPackage";
2709 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2710 return null;
2711 }
2712
Svet Ganov354cd3c2015-12-17 11:35:04 -08002713 if (!parseAllMetaData(res, parser, "<instrumentation>", a,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 outError)) {
2715 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2716 return null;
2717 }
2718
2719 owner.instrumentation.add(a);
2720
2721 return a;
2722 }
2723
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002724 /**
2725 * Parse the {@code application} XML tree at the current parse location in a
2726 * <em>base APK</em> manifest.
2727 * <p>
2728 * When adding new features, carefully consider if they should also be
2729 * supported by split APKs.
2730 */
2731 private boolean parseBaseApplication(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002732 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002733 throws XmlPullParserException, IOException {
2734 final ApplicationInfo ai = owner.applicationInfo;
2735 final String pkgName = owner.applicationInfo.packageName;
2736
Svet Ganov354cd3c2015-12-17 11:35:04 -08002737 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002738 com.android.internal.R.styleable.AndroidManifestApplication);
2739
Todd Kennedybb8a42d2016-06-02 14:13:56 -07002740 if (!parsePackageItemInfo(owner, ai, outError,
2741 "<application>", sa, false /*nameRequired*/,
2742 com.android.internal.R.styleable.AndroidManifestApplication_name,
2743 com.android.internal.R.styleable.AndroidManifestApplication_label,
2744 com.android.internal.R.styleable.AndroidManifestApplication_icon,
2745 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon,
2746 com.android.internal.R.styleable.AndroidManifestApplication_logo,
2747 com.android.internal.R.styleable.AndroidManifestApplication_banner)) {
2748 sa.recycle();
2749 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2750 return false;
2751 }
2752
2753 if (ai.name != null) {
Todd Kennedyafb52692016-08-22 15:44:00 -07002754 ai.className = ai.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002755 }
2756
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002757 String manageSpaceActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002758 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
2759 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002760 if (manageSpaceActivity != null) {
2761 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
2762 outError);
2763 }
2764
Christopher Tate181fafa2009-05-14 11:12:14 -07002765 boolean allowBackup = sa.getBoolean(
2766 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
2767 if (allowBackup) {
2768 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07002769
Christopher Tate43fbc5f2016-02-17 18:00:48 -08002770 // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
2771 // and restoreAnyVersion are only relevant if backup is possible for the
2772 // given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002773 String backupAgent = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002774 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
2775 Configuration.NATIVE_CONFIG_VERSION);
Christopher Tate181fafa2009-05-14 11:12:14 -07002776 if (backupAgent != null) {
2777 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07002778 if (DEBUG_BACKUP) {
2779 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002780 + " from " + pkgName + "+" + backupAgent);
2781 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07002782
2783 if (sa.getBoolean(
2784 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
2785 true)) {
2786 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
2787 }
2788 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08002789 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
2790 false)) {
2791 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
2792 }
Christopher Tated1de2562014-06-17 17:12:35 -07002793 if (sa.getBoolean(
2794 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
2795 false)) {
2796 ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
2797 }
Christopher Tate43fbc5f2016-02-17 18:00:48 -08002798 if (sa.getBoolean(
2799 com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
2800 false)) {
2801 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
2802 }
Christopher Tate181fafa2009-05-14 11:12:14 -07002803 }
Matthew Williams303650c2015-04-17 18:22:51 -07002804
2805 TypedValue v = sa.peekValue(
2806 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
2807 if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
2808 if (DEBUG_BACKUP) {
2809 Slog.v(TAG, "fullBackupContent specified as boolean=" +
2810 (v.data == 0 ? "false" : "true"));
2811 }
2812 // "false" => -1, "true" => 0
2813 ai.fullBackupContent = (v.data == 0 ? -1 : 0);
2814 }
2815 if (DEBUG_BACKUP) {
2816 Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
2817 }
Christopher Tate181fafa2009-05-14 11:12:14 -07002818 }
Christopher Tate4a627c72011-04-01 14:43:32 -07002819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002820 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08002821 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002822 ai.descriptionRes = sa.getResourceId(
2823 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
2824
2825 if ((flags&PARSE_IS_SYSTEM) != 0) {
2826 if (sa.getBoolean(
2827 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
2828 false)) {
2829 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
2830 }
Amith Yamasani0d8750d2013-05-01 15:25:28 -07002831 }
2832
2833 if (sa.getBoolean(
2834 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
2835 false)) {
2836 owner.mRequiredForAllUsers = true;
Amith Yamasanie993ae12013-04-15 13:42:57 -07002837 }
2838
2839 String restrictedAccountType = sa.getString(com.android.internal.R.styleable
2840 .AndroidManifestApplication_restrictedAccountType);
2841 if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
2842 owner.mRestrictedAccountType = restrictedAccountType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002843 }
2844
Amith Yamasaniccbe3892013-04-12 17:52:42 -07002845 String requiredAccountType = sa.getString(com.android.internal.R.styleable
2846 .AndroidManifestApplication_requiredAccountType);
2847 if (requiredAccountType != null && requiredAccountType.length() > 0) {
2848 owner.mRequiredAccountType = requiredAccountType;
2849 }
2850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851 if (sa.getBoolean(
2852 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
2853 false)) {
2854 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
2855 }
2856
2857 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07002858 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08002859 false)) {
2860 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
2861 }
2862
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002863 owner.baseHardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07002864 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07002865 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Alan Viveretted70b9e72015-05-27 14:29:20 -07002866 if (owner.baseHardwareAccelerated) {
2867 ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
2868 }
Romain Guy812ccbe2010-06-01 14:07:24 -07002869
2870 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002871 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
2872 true)) {
2873 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
2874 }
2875
2876 if (sa.getBoolean(
2877 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
2878 false)) {
2879 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
2880 }
2881
2882 if (sa.getBoolean(
2883 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
2884 true)) {
2885 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
2886 }
2887
Svet Ganov354cd3c2015-12-17 11:35:04 -08002888 // The parent package controls installation, hence specify test only installs.
2889 if (owner.parentPackage == null) {
2890 if (sa.getBoolean(
2891 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
2892 false)) {
2893 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
2894 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07002895 }
2896
Jason parksa3cdaa52011-01-13 14:15:43 -06002897 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08002898 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06002899 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08002900 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06002901 }
2902
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07002903 if (sa.getBoolean(
Alex Klyubin01a959d2015-03-18 10:05:45 -07002904 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
2905 true)) {
2906 ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
2907 }
2908
2909 if (sa.getBoolean(
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07002910 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
2911 false /* default is no RTL support*/)) {
2912 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
2913 }
2914
Narayan Kamath589a1bc2014-07-03 14:43:26 +01002915 if (sa.getBoolean(
2916 com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
2917 false)) {
2918 ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
2919 }
2920
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07002921 if (sa.getBoolean(
2922 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
2923 true)) {
2924 ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
2925 }
2926
Todd Kennedyd022ac22016-04-13 10:49:29 -07002927 if (sa.getBoolean(
2928 R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
2929 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06002930 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
Jeff Sharkeye17ac152015-11-06 22:40:29 -08002931 }
Todd Kennedyd022ac22016-04-13 10:49:29 -07002932 if (sa.getBoolean(
2933 R.styleable.AndroidManifestApplication_directBootAware,
2934 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06002935 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002936 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08002937
Wale Ogunwale6afdf912016-01-30 13:01:33 -08002938 if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity,
2939 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N)) {
2940 ai.privateFlags |= PRIVATE_FLAG_RESIZEABLE_ACTIVITIES;
2941 }
2942
Chad Brubakerc845b2a2016-05-13 14:09:27 -07002943 ai.networkSecurityConfigRes = sa.getResourceId(
2944 com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig,
2945 0);
2946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002947 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002948 str = sa.getNonConfigurationString(
2949 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002950 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
2951
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002952 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
2953 str = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002954 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
2955 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002956 } else {
2957 // Some older apps have been seen to use a resource reference
2958 // here that on older builds was ignored (with a warning). We
2959 // need to continue to do this for them so they don't break.
2960 str = sa.getNonResourceString(
2961 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
2962 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002963 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
2964 str, outError);
2965
2966 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002967 CharSequence pname;
2968 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
2969 pname = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002970 com.android.internal.R.styleable.AndroidManifestApplication_process,
2971 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002972 } else {
2973 // Some older apps have been seen to use a resource reference
2974 // here that on older builds was ignored (with a warning). We
2975 // need to continue to do this for them so they don't break.
2976 pname = sa.getNonResourceString(
2977 com.android.internal.R.styleable.AndroidManifestApplication_process);
2978 }
2979 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002980 flags, mSeparateProcesses, outError);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002981
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002982 ai.enabled = sa.getBoolean(
2983 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002984
Jose Lima12d0b4c2014-03-14 16:55:12 -07002985 if (sa.getBoolean(
2986 com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
2987 ai.flags |= ApplicationInfo.FLAG_IS_GAME;
2988 }
2989
Dianne Hackborn02486b12010-08-26 14:18:37 -07002990 if (false) {
2991 if (sa.getBoolean(
2992 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
2993 false)) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08002994 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07002995
2996 // A heavy-weight application can not be in a custom process.
2997 // We can do direct compare because we intern all strings.
2998 if (ai.processName != null && ai.processName != ai.packageName) {
2999 outError[0] = "cantSaveState applications can not use custom processes";
3000 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003001 }
3002 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003003 }
3004
Adam Powell269248d2011-08-02 10:26:54 -07003005 ai.uiOptions = sa.getInt(
3006 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
3007
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003008 sa.recycle();
3009
3010 if (outError[0] != null) {
3011 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3012 return false;
3013 }
3014
3015 final int innerDepth = parser.getDepth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003016 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07003017 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3018 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3019 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003020 continue;
3021 }
3022
3023 String tagName = parser.getName();
3024 if (tagName.equals("activity")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003025 Activity a = parseActivity(owner, res, parser, flags, outError, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003026 owner.baseHardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003027 if (a == null) {
3028 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3029 return false;
3030 }
3031
3032 owner.activities.add(a);
3033
3034 } else if (tagName.equals("receiver")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003035 Activity a = parseActivity(owner, res, parser, flags, outError, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003036 if (a == null) {
3037 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3038 return false;
3039 }
3040
3041 owner.receivers.add(a);
3042
3043 } else if (tagName.equals("service")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003044 Service s = parseService(owner, res, parser, flags, outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003045 if (s == null) {
3046 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3047 return false;
3048 }
3049
3050 owner.services.add(s);
3051
3052 } else if (tagName.equals("provider")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003053 Provider p = parseProvider(owner, res, parser, flags, outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 if (p == null) {
3055 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3056 return false;
3057 }
3058
3059 owner.providers.add(p);
3060
3061 } else if (tagName.equals("activity-alias")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003062 Activity a = parseActivityAlias(owner, res, parser, flags, outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003063 if (a == null) {
3064 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3065 return false;
3066 }
3067
3068 owner.activities.add(a);
3069
3070 } else if (parser.getName().equals("meta-data")) {
3071 // note: application meta-data is stored off to the side, so it can
3072 // remain null in the primary copy (we like to avoid extra copies because
3073 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003074 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003075 outError)) == null) {
3076 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3077 return false;
3078 }
3079
Dianne Hackbornc895be72013-03-11 17:48:43 -07003080 } else if (tagName.equals("library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003081 sa = res.obtainAttributes(parser,
Dianne Hackbornc895be72013-03-11 17:48:43 -07003082 com.android.internal.R.styleable.AndroidManifestLibrary);
3083
3084 // Note: don't allow this value to be a reference to a resource
3085 // that may change.
3086 String lname = sa.getNonResourceString(
3087 com.android.internal.R.styleable.AndroidManifestLibrary_name);
3088
3089 sa.recycle();
3090
3091 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003092 lname = lname.intern();
3093 if (!ArrayUtils.contains(owner.libraryNames, lname)) {
3094 owner.libraryNames = ArrayUtils.add(owner.libraryNames, lname);
Dianne Hackbornc895be72013-03-11 17:48:43 -07003095 }
3096 }
3097
3098 XmlUtils.skipCurrentTag(parser);
3099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003100 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003101 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003102 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3103
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003104 // Note: don't allow this value to be a reference to a resource
3105 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003106 String lname = sa.getNonResourceString(
3107 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07003108 boolean req = sa.getBoolean(
3109 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3110 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003111
3112 sa.recycle();
3113
Dianne Hackborn49237342009-08-27 20:08:01 -07003114 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003115 lname = lname.intern();
Dianne Hackborn49237342009-08-27 20:08:01 -07003116 if (req) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003117 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07003118 } else {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003119 owner.usesOptionalLibraries = ArrayUtils.add(
3120 owner.usesOptionalLibraries, lname);
3121 }
3122 }
3123
3124 XmlUtils.skipCurrentTag(parser);
3125
3126 } else if (tagName.equals("uses-package")) {
3127 // Dependencies for app installers; we don't currently try to
3128 // enforce this.
3129 XmlUtils.skipCurrentTag(parser);
3130
3131 } else {
3132 if (!RIGID_PARSER) {
3133 Slog.w(TAG, "Unknown element under <application>: " + tagName
3134 + " at " + mArchiveSourcePath + " "
3135 + parser.getPositionDescription());
3136 XmlUtils.skipCurrentTag(parser);
3137 continue;
3138 } else {
3139 outError[0] = "Bad element under <application>: " + tagName;
3140 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3141 return false;
3142 }
3143 }
3144 }
3145
Narayan Kamathb12dcfb2015-03-30 11:31:04 +01003146 modifySharedLibrariesForBackwardCompatibility(owner);
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00003147
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003148 if (hasDomainURLs(owner)) {
3149 owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3150 } else {
3151 owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3152 }
3153
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003154 return true;
3155 }
3156
Narayan Kamathb12dcfb2015-03-30 11:31:04 +01003157 private static void modifySharedLibrariesForBackwardCompatibility(Package owner) {
3158 // "org.apache.http.legacy" is now a part of the boot classpath so it doesn't need
3159 // to be an explicit dependency.
3160 //
3161 // A future change will remove this library from the boot classpath, at which point
3162 // all apps that target SDK 21 and earlier will have it automatically added to their
3163 // dependency lists.
3164 owner.usesLibraries = ArrayUtils.remove(owner.usesLibraries, "org.apache.http.legacy");
3165 owner.usesOptionalLibraries = ArrayUtils.remove(owner.usesOptionalLibraries,
3166 "org.apache.http.legacy");
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00003167 }
3168
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003169 /**
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003170 * Check if one of the IntentFilter as both actions DEFAULT / VIEW and a HTTP/HTTPS data URI
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003171 */
3172 private static boolean hasDomainURLs(Package pkg) {
3173 if (pkg == null || pkg.activities == null) return false;
3174 final ArrayList<Activity> activities = pkg.activities;
3175 final int countActivities = activities.size();
3176 for (int n=0; n<countActivities; n++) {
3177 Activity activity = activities.get(n);
3178 ArrayList<ActivityIntentInfo> filters = activity.intents;
3179 if (filters == null) continue;
3180 final int countFilters = filters.size();
3181 for (int m=0; m<countFilters; m++) {
3182 ActivityIntentInfo aii = filters.get(m);
3183 if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003184 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003185 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
3186 aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
3187 return true;
3188 }
3189 }
3190 }
3191 return false;
3192 }
3193
3194 /**
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003195 * Parse the {@code application} XML tree at the current parse location in a
3196 * <em>split APK</em> manifest.
3197 * <p>
3198 * Note that split APKs have many more restrictions on what they're capable
3199 * of doing, so many valid features of a base APK have been carefully
3200 * omitted here.
3201 */
Svet Ganov354cd3c2015-12-17 11:35:04 -08003202 private boolean parseSplitApplication(Package owner, Resources res, XmlResourceParser parser,
3203 int flags, int splitIndex, String[] outError)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003204 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003205 TypedArray sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003206 com.android.internal.R.styleable.AndroidManifestApplication);
3207
3208 if (sa.getBoolean(
3209 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
3210 owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
3211 }
3212
3213 final int innerDepth = parser.getDepth();
3214 int type;
3215 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3216 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3217 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3218 continue;
3219 }
3220
3221 String tagName = parser.getName();
3222 if (tagName.equals("activity")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003223 Activity a = parseActivity(owner, res, parser, flags, outError, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003224 owner.baseHardwareAccelerated);
3225 if (a == null) {
3226 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3227 return false;
3228 }
3229
3230 owner.activities.add(a);
3231
3232 } else if (tagName.equals("receiver")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003233 Activity a = parseActivity(owner, res, parser, flags, outError, true, false);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003234 if (a == null) {
3235 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3236 return false;
3237 }
3238
3239 owner.receivers.add(a);
3240
3241 } else if (tagName.equals("service")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003242 Service s = parseService(owner, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003243 if (s == null) {
3244 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3245 return false;
3246 }
3247
3248 owner.services.add(s);
3249
3250 } else if (tagName.equals("provider")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003251 Provider p = parseProvider(owner, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003252 if (p == null) {
3253 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3254 return false;
3255 }
3256
3257 owner.providers.add(p);
3258
3259 } else if (tagName.equals("activity-alias")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003260 Activity a = parseActivityAlias(owner, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003261 if (a == null) {
3262 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3263 return false;
3264 }
3265
3266 owner.activities.add(a);
3267
3268 } else if (parser.getName().equals("meta-data")) {
3269 // note: application meta-data is stored off to the side, so it can
3270 // remain null in the primary copy (we like to avoid extra copies because
3271 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003272 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003273 outError)) == null) {
3274 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3275 return false;
3276 }
3277
3278 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003279 sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003280 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3281
3282 // Note: don't allow this value to be a reference to a resource
3283 // that may change.
3284 String lname = sa.getNonResourceString(
3285 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
3286 boolean req = sa.getBoolean(
3287 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3288 true);
3289
3290 sa.recycle();
3291
3292 if (lname != null) {
3293 lname = lname.intern();
3294 if (req) {
3295 // Upgrade to treat as stronger constraint
3296 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
3297 owner.usesOptionalLibraries = ArrayUtils.remove(
3298 owner.usesOptionalLibraries, lname);
3299 } else {
3300 // Ignore if someone already defined as required
3301 if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
3302 owner.usesOptionalLibraries = ArrayUtils.add(
3303 owner.usesOptionalLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07003304 }
3305 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003306 }
3307
3308 XmlUtils.skipCurrentTag(parser);
3309
Dianne Hackborncef65ee2010-09-30 18:27:22 -07003310 } else if (tagName.equals("uses-package")) {
3311 // Dependencies for app installers; we don't currently try to
3312 // enforce this.
3313 XmlUtils.skipCurrentTag(parser);
3314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 } else {
3316 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003317 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003318 + " at " + mArchiveSourcePath + " "
3319 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003320 XmlUtils.skipCurrentTag(parser);
3321 continue;
3322 } else {
3323 outError[0] = "Bad element under <application>: " + tagName;
3324 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3325 return false;
3326 }
3327 }
3328 }
3329
3330 return true;
3331 }
3332
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003333 private static boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
3334 String[] outError, String tag, TypedArray sa, boolean nameRequired,
3335 int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) {
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003336 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003337 if (name == null) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003338 if (nameRequired) {
3339 outError[0] = tag + " does not specify android:name";
3340 return false;
3341 }
3342 } else {
3343 outInfo.name
3344 = buildClassName(owner.applicationInfo.packageName, name, outError);
3345 if (outInfo.name == null) {
3346 return false;
3347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003348 }
3349
Todd Kennedya83bfca2016-06-03 07:52:17 -07003350 final boolean useRoundIcon =
3351 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
3352 int roundIconVal = useRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003353 if (roundIconVal != 0) {
3354 outInfo.icon = roundIconVal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003355 outInfo.nonLocalizedLabel = null;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003356 } else {
3357 int iconVal = sa.getResourceId(iconRes, 0);
3358 if (iconVal != 0) {
3359 outInfo.icon = iconVal;
3360 outInfo.nonLocalizedLabel = null;
3361 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003362 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003363
Adam Powell81cd2e92010-04-21 16:35:18 -07003364 int logoVal = sa.getResourceId(logoRes, 0);
3365 if (logoVal != 0) {
3366 outInfo.logo = logoVal;
3367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003368
Jose Limaf78e3122014-03-06 12:13:15 -08003369 int bannerVal = sa.getResourceId(bannerRes, 0);
3370 if (bannerVal != 0) {
3371 outInfo.banner = bannerVal;
3372 }
3373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003374 TypedValue v = sa.peekValue(labelRes);
3375 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
3376 outInfo.nonLocalizedLabel = v.coerceToString();
3377 }
3378
3379 outInfo.packageName = owner.packageName;
3380
3381 return true;
3382 }
3383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003384 private Activity parseActivity(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003385 XmlResourceParser parser, int flags, String[] outError,
Romain Guy529b60a2010-08-03 18:05:47 -07003386 boolean receiver, boolean hardwareAccelerated)
3387 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003388 TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003389
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003390 if (mParseActivityArgs == null) {
3391 mParseActivityArgs = new ParseComponentArgs(owner, outError,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003392 R.styleable.AndroidManifestActivity_name,
3393 R.styleable.AndroidManifestActivity_label,
3394 R.styleable.AndroidManifestActivity_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003395 R.styleable.AndroidManifestActivity_roundIcon,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003396 R.styleable.AndroidManifestActivity_logo,
3397 R.styleable.AndroidManifestActivity_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003398 mSeparateProcesses,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003399 R.styleable.AndroidManifestActivity_process,
3400 R.styleable.AndroidManifestActivity_description,
3401 R.styleable.AndroidManifestActivity_enabled);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003402 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003403
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003404 mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
3405 mParseActivityArgs.sa = sa;
3406 mParseActivityArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003407
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003408 Activity a = new Activity(mParseActivityArgs, new ActivityInfo());
3409 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003410 sa.recycle();
3411 return null;
3412 }
3413
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003414 boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003415 if (setExported) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003416 a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003417 }
3418
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003419 a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003420
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003421 a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
Adam Powell269248d2011-08-02 10:26:54 -07003422 a.info.applicationInfo.uiOptions);
3423
Adam Powelldd8fab22012-03-22 17:47:27 -07003424 String parentName = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003425 R.styleable.AndroidManifestActivity_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003426 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07003427 if (parentName != null) {
3428 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
3429 if (outError[0] == null) {
3430 a.info.parentActivityName = parentClassName;
3431 } else {
3432 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
3433 parentName);
3434 outError[0] = null;
3435 }
3436 }
3437
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003438 String str;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003439 str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440 if (str == null) {
3441 a.info.permission = owner.applicationInfo.permission;
3442 } else {
3443 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
3444 }
3445
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003446 str = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003447 R.styleable.AndroidManifestActivity_taskAffinity,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003448 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003449 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
3450 owner.applicationInfo.taskAffinity, str, outError);
3451
3452 a.info.flags = 0;
3453 if (sa.getBoolean(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003454 R.styleable.AndroidManifestActivity_multiprocess, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003455 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
3456 }
3457
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003458 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003459 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
3460 }
3461
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003462 if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003463 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
3464 }
3465
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003466 if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003467 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
3468 }
3469
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003470 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003471 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
3472 }
3473
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003474 if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003475 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
3476 }
3477
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003478 if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
3480 }
3481
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003482 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003483 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
3484 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
3485 }
3486
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003487 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
Dianne Hackbornffa42482009-09-23 22:20:11 -07003488 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
3489 }
3490
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07003491 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
3492 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
3493 a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Craig Mautner5962b122012-10-05 14:45:52 -07003494 }
3495
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003496 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
Daniel Sandler613dde42010-06-21 13:46:39 -04003497 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
3498 }
Craig Mautner5962b122012-10-05 14:45:52 -07003499
Fyodor Kupolov4f5de342015-08-25 10:08:45 -07003500 if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
3501 a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
Fyodor Kupolov703d1c42015-01-27 11:59:00 -08003502 }
3503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 if (!receiver) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003505 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07003506 hardwareAccelerated)) {
3507 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
3508 }
3509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003510 a.info.launchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003511 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
Craig Mautner2dac0562014-05-06 09:06:44 -07003512 a.info.documentLaunchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003513 R.styleable.AndroidManifestActivity_documentLaunchMode,
Craig Mautner2dac0562014-05-06 09:06:44 -07003514 ActivityInfo.DOCUMENT_LAUNCH_NONE);
Craig Mautnerffcfcaa2014-06-05 09:54:38 -07003515 a.info.maxRecents = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003516 R.styleable.AndroidManifestActivity_maxRecents,
Dianne Hackborn852975d2014-08-22 17:42:43 -07003517 ActivityManager.getDefaultAppRecentsLimitStatic());
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003518 a.info.configChanges = sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003519 a.info.softInputMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003520 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
Craig Mautner2dac0562014-05-06 09:06:44 -07003521
Craig Mautner43e52ed2014-06-16 17:18:52 -07003522 a.info.persistableMode = sa.getInteger(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003523 R.styleable.AndroidManifestActivity_persistableMode,
Craig Mautner43e52ed2014-06-16 17:18:52 -07003524 ActivityInfo.PERSIST_ROOT_ONLY);
Craig Mautner2dac0562014-05-06 09:06:44 -07003525
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003526 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07003527 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
3528 }
3529
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003530 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07003531 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
3532 }
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07003533
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003534 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07003535 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
3536 }
Dianne Hackborna4e102e2014-09-04 22:52:27 -07003537
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003538 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
Dianne Hackborna4e102e2014-09-04 22:52:27 -07003539 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
3540 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003541
Wale Ogunwaled26176f2016-01-25 20:04:04 -08003542 a.info.screenOrientation = sa.getInt(
3543 R.styleable.AndroidManifestActivity_screenOrientation,
3544 SCREEN_ORIENTATION_UNSPECIFIED);
Wale Ogunwale6a591362015-10-05 20:18:27 -07003545
Wale Ogunwaled26176f2016-01-25 20:04:04 -08003546 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale163828d2016-02-01 11:48:19 -08003547 final boolean appDefault = (owner.applicationInfo.privateFlags
3548 & PRIVATE_FLAG_RESIZEABLE_ACTIVITIES) != 0;
Andrii Kulian3f8dc152016-05-17 19:07:24 -07003549 // This flag is used to workaround the issue with ignored resizeableActivity param when
3550 // either targetSdkVersion is not set at all or <uses-sdk> tag is below <application>
3551 // tag in AndroidManifest. If this param was explicitly set to 'false' we need to set
3552 // corresponding resizeMode regardless of targetSdkVersion value at this point in time.
3553 final boolean resizeableSetExplicitly
3554 = sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity);
Wale Ogunwale163828d2016-02-01 11:48:19 -08003555 final boolean resizeable = sa.getBoolean(
3556 R.styleable.AndroidManifestActivity_resizeableActivity, appDefault);
3557
3558 if (resizeable) {
3559 if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
3560 false)) {
3561 a.info.resizeMode = RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
3562 } else {
3563 a.info.resizeMode = RESIZE_MODE_RESIZEABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08003564 }
Andrii Kulian3f8dc152016-05-17 19:07:24 -07003565 } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N
3566 || resizeableSetExplicitly) {
Wale Ogunwale163828d2016-02-01 11:48:19 -08003567 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale508ff552016-02-15 19:31:50 -08003568 } else if (!a.info.isFixedOrientation() && (a.info.flags & FLAG_IMMERSIVE) == 0) {
Wale Ogunwaled829d362016-02-10 19:24:49 -08003569 a.info.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08003570 }
3571
3572 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
Wale Ogunwaled26176f2016-01-25 20:04:04 -08003573 a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08003574 }
Wale Ogunwaleb60692e2015-10-24 12:35:56 -07003575
Craig Mautner15df08a2015-04-01 12:17:18 -07003576 a.info.lockTaskLaunchMode =
3577 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003578
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003579 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
3580 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07003581 false);
Ruben Brunkf56c9f42016-04-22 18:20:55 -07003582
3583 a.info.requestedVrComponent =
3584 sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003585 } else {
3586 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
3587 a.info.configChanges = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003588
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003589 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07003590 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003591 if (a.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003592 Slog.w(TAG, "Activity exported request ignored due to singleUser: "
3593 + a.className + " at " + mArchiveSourcePath + " "
3594 + parser.getPositionDescription());
3595 a.info.exported = false;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003596 setExported = true;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003597 }
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003598 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003599
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003600 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
3601 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07003602 false);
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003603 }
3604
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003605 if (a.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07003606 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003607 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07003608 }
3609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003610 sa.recycle();
3611
Alex Klyubinb9f8a522015-02-03 11:12:59 -08003612 if (receiver && (owner.applicationInfo.privateFlags
3613 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07003614 // A heavy-weight application can not have receives in its main process
3615 // We can do direct compare because we intern all strings.
3616 if (a.info.processName == owner.packageName) {
3617 outError[0] = "Heavy-weight applications can not have receivers in main process";
3618 }
3619 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003621 if (outError[0] != null) {
3622 return null;
3623 }
3624
3625 int outerDepth = parser.getDepth();
3626 int type;
3627 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3628 && (type != XmlPullParser.END_TAG
3629 || parser.getDepth() > outerDepth)) {
3630 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3631 continue;
3632 }
3633
3634 if (parser.getName().equals("intent-filter")) {
3635 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Svet Ganov354cd3c2015-12-17 11:35:04 -08003636 if (!parseIntent(res, parser, true, true, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003637 return null;
3638 }
3639 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003640 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07003641 + mArchiveSourcePath + " "
3642 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003643 } else {
3644 a.intents.add(intent);
3645 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07003646 } else if (!receiver && parser.getName().equals("preferred")) {
3647 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Svet Ganov354cd3c2015-12-17 11:35:04 -08003648 if (!parseIntent(res, parser, false, false, intent, outError)) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07003649 return null;
3650 }
3651 if (intent.countActions() == 0) {
3652 Slog.w(TAG, "No actions in preferred at "
3653 + mArchiveSourcePath + " "
3654 + parser.getPositionDescription());
3655 } else {
3656 if (owner.preferredActivityFilters == null) {
3657 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
3658 }
3659 owner.preferredActivityFilters.add(intent);
3660 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003661 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003662 if ((a.metaData = parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003663 outError)) == null) {
3664 return null;
3665 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003666 } else if (!receiver && parser.getName().equals("layout")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003667 parseLayout(res, parser, a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003668 } else {
3669 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003670 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003671 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003672 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003673 + " at " + mArchiveSourcePath + " "
3674 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003675 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07003676 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003677 + " at " + mArchiveSourcePath + " "
3678 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003679 }
3680 XmlUtils.skipCurrentTag(parser);
3681 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003682 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07003683 if (receiver) {
3684 outError[0] = "Bad element under <receiver>: " + parser.getName();
3685 } else {
3686 outError[0] = "Bad element under <activity>: " + parser.getName();
3687 }
3688 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003689 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003690 }
3691 }
3692
3693 if (!setExported) {
3694 a.info.exported = a.intents.size() > 0;
3695 }
3696
3697 return a;
3698 }
3699
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003700 private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003701 TypedArray sw = res.obtainAttributes(attrs,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003702 com.android.internal.R.styleable.AndroidManifestLayout);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003703 int width = -1;
3704 float widthFraction = -1f;
3705 int height = -1;
3706 float heightFraction = -1f;
3707 final int widthType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003708 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003709 if (widthType == TypedValue.TYPE_FRACTION) {
3710 widthFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003711 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003712 1, 1, -1);
3713 } else if (widthType == TypedValue.TYPE_DIMENSION) {
3714 width = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003715 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003716 -1);
3717 }
3718 final int heightType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003719 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003720 if (heightType == TypedValue.TYPE_FRACTION) {
3721 heightFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003722 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003723 1, 1, -1);
3724 } else if (heightType == TypedValue.TYPE_DIMENSION) {
3725 height = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003726 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003727 -1);
3728 }
3729 int gravity = sw.getInt(
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003730 com.android.internal.R.styleable.AndroidManifestLayout_gravity,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003731 Gravity.CENTER);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07003732 int minWidth = sw.getDimensionPixelSize(
3733 com.android.internal.R.styleable.AndroidManifestLayout_minWidth,
Andrii Kulian2e751b82016-03-16 16:59:32 -07003734 -1);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07003735 int minHeight = sw.getDimensionPixelSize(
3736 com.android.internal.R.styleable.AndroidManifestLayout_minHeight,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003737 -1);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003738 sw.recycle();
Andrii Kulian2e751b82016-03-16 16:59:32 -07003739 a.info.windowLayout = new ActivityInfo.WindowLayout(width, widthFraction,
Andrii Kulianf66a83d2016-05-17 12:17:44 -07003740 height, heightFraction, gravity, minWidth, minHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003741 }
3742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003743 private Activity parseActivityAlias(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003744 XmlResourceParser parser, int flags, String[] outError)
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003745 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003746 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003747 com.android.internal.R.styleable.AndroidManifestActivityAlias);
3748
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003749 String targetActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003750 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
3751 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003752 if (targetActivity == null) {
3753 outError[0] = "<activity-alias> does not specify android:targetActivity";
3754 sa.recycle();
3755 return null;
3756 }
3757
3758 targetActivity = buildClassName(owner.applicationInfo.packageName,
3759 targetActivity, outError);
3760 if (targetActivity == null) {
3761 sa.recycle();
3762 return null;
3763 }
3764
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003765 if (mParseActivityAliasArgs == null) {
3766 mParseActivityAliasArgs = new ParseComponentArgs(owner, outError,
3767 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
3768 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
3769 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003770 com.android.internal.R.styleable.AndroidManifestActivityAlias_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07003771 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08003772 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003773 mSeparateProcesses,
3774 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003775 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003776 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
3777 mParseActivityAliasArgs.tag = "<activity-alias>";
3778 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003779
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003780 mParseActivityAliasArgs.sa = sa;
3781 mParseActivityAliasArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003783 Activity target = null;
3784
3785 final int NA = owner.activities.size();
3786 for (int i=0; i<NA; i++) {
3787 Activity t = owner.activities.get(i);
3788 if (targetActivity.equals(t.info.name)) {
3789 target = t;
3790 break;
3791 }
3792 }
3793
3794 if (target == null) {
3795 outError[0] = "<activity-alias> target activity " + targetActivity
3796 + " not found in manifest";
3797 sa.recycle();
3798 return null;
3799 }
3800
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003801 ActivityInfo info = new ActivityInfo();
3802 info.targetActivity = targetActivity;
3803 info.configChanges = target.info.configChanges;
3804 info.flags = target.info.flags;
3805 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07003806 info.logo = target.info.logo;
Jose Limaf78e3122014-03-06 12:13:15 -08003807 info.banner = target.info.banner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003808 info.labelRes = target.info.labelRes;
3809 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
3810 info.launchMode = target.info.launchMode;
Yao Chen597ad3f2015-06-09 16:00:14 -07003811 info.lockTaskLaunchMode = target.info.lockTaskLaunchMode;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003812 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003813 if (info.descriptionRes == 0) {
3814 info.descriptionRes = target.info.descriptionRes;
3815 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003816 info.screenOrientation = target.info.screenOrientation;
3817 info.taskAffinity = target.info.taskAffinity;
3818 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07003819 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07003820 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07003821 info.parentActivityName = target.info.parentActivityName;
Craig Mautner8307ea72014-09-11 15:03:53 -07003822 info.maxRecents = target.info.maxRecents;
Andrii Kulian2e751b82016-03-16 16:59:32 -07003823 info.windowLayout = target.info.windowLayout;
Wale Ogunwaled26176f2016-01-25 20:04:04 -08003824 info.resizeMode = target.info.resizeMode;
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003825 info.encryptionAware = info.directBootAware = target.info.directBootAware;
Craig Mautner8307ea72014-09-11 15:03:53 -07003826
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003827 Activity a = new Activity(mParseActivityAliasArgs, info);
3828 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003829 sa.recycle();
3830 return null;
3831 }
3832
3833 final boolean setExported = sa.hasValue(
3834 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
3835 if (setExported) {
3836 a.info.exported = sa.getBoolean(
3837 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
3838 }
3839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003840 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003841 str = sa.getNonConfigurationString(
3842 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003843 if (str != null) {
3844 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
3845 }
3846
Adam Powelldd8fab22012-03-22 17:47:27 -07003847 String parentName = sa.getNonConfigurationString(
3848 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003849 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07003850 if (parentName != null) {
3851 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
3852 if (outError[0] == null) {
3853 a.info.parentActivityName = parentClassName;
3854 } else {
3855 Log.e(TAG, "Activity alias " + a.info.name +
3856 " specified invalid parentActivityName " + parentName);
3857 outError[0] = null;
3858 }
3859 }
3860
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003861 sa.recycle();
3862
3863 if (outError[0] != null) {
3864 return null;
3865 }
3866
3867 int outerDepth = parser.getDepth();
3868 int type;
3869 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3870 && (type != XmlPullParser.END_TAG
3871 || parser.getDepth() > outerDepth)) {
3872 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3873 continue;
3874 }
3875
3876 if (parser.getName().equals("intent-filter")) {
3877 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Svet Ganov354cd3c2015-12-17 11:35:04 -08003878 if (!parseIntent(res, parser, true, true, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003879 return null;
3880 }
3881 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003882 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07003883 + mArchiveSourcePath + " "
3884 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003885 } else {
3886 a.intents.add(intent);
3887 }
3888 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003889 if ((a.metaData=parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 outError)) == null) {
3891 return null;
3892 }
3893 } else {
3894 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003895 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003896 + " at " + mArchiveSourcePath + " "
3897 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003898 XmlUtils.skipCurrentTag(parser);
3899 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003900 } else {
3901 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
3902 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003904 }
3905 }
3906
3907 if (!setExported) {
3908 a.info.exported = a.intents.size() > 0;
3909 }
3910
3911 return a;
3912 }
3913
3914 private Provider parseProvider(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003915 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003916 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003917 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003918 com.android.internal.R.styleable.AndroidManifestProvider);
3919
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003920 if (mParseProviderArgs == null) {
3921 mParseProviderArgs = new ParseComponentArgs(owner, outError,
3922 com.android.internal.R.styleable.AndroidManifestProvider_name,
3923 com.android.internal.R.styleable.AndroidManifestProvider_label,
3924 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003925 com.android.internal.R.styleable.AndroidManifestProvider_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07003926 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08003927 com.android.internal.R.styleable.AndroidManifestProvider_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003928 mSeparateProcesses,
3929 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003930 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003931 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
3932 mParseProviderArgs.tag = "<provider>";
3933 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003934
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003935 mParseProviderArgs.sa = sa;
3936 mParseProviderArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003937
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003938 Provider p = new Provider(mParseProviderArgs, new ProviderInfo());
3939 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003940 sa.recycle();
3941 return null;
3942 }
3943
Nick Kralevichf097b162012-07-28 12:43:48 -07003944 boolean providerExportedDefault = false;
3945
3946 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
3947 // For compatibility, applications targeting API level 16 or lower
3948 // should have their content providers exported by default, unless they
3949 // specify otherwise.
3950 providerExportedDefault = true;
3951 }
3952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003953 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07003954 com.android.internal.R.styleable.AndroidManifestProvider_exported,
3955 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003956
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003957 String cpname = sa.getNonConfigurationString(
3958 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003959
3960 p.info.isSyncable = sa.getBoolean(
3961 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
3962 false);
3963
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003964 String permission = sa.getNonConfigurationString(
3965 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
3966 String str = sa.getNonConfigurationString(
3967 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003968 if (str == null) {
3969 str = permission;
3970 }
3971 if (str == null) {
3972 p.info.readPermission = owner.applicationInfo.permission;
3973 } else {
3974 p.info.readPermission =
3975 str.length() > 0 ? str.toString().intern() : null;
3976 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003977 str = sa.getNonConfigurationString(
3978 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003979 if (str == null) {
3980 str = permission;
3981 }
3982 if (str == null) {
3983 p.info.writePermission = owner.applicationInfo.permission;
3984 } else {
3985 p.info.writePermission =
3986 str.length() > 0 ? str.toString().intern() : null;
3987 }
3988
3989 p.info.grantUriPermissions = sa.getBoolean(
3990 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
3991 false);
3992
3993 p.info.multiprocess = sa.getBoolean(
3994 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
3995 false);
3996
3997 p.info.initOrder = sa.getInt(
3998 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
3999 0);
4000
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004001 p.info.flags = 0;
4002
4003 if (sa.getBoolean(
4004 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
4005 false)) {
4006 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07004007 if (p.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004008 Slog.w(TAG, "Provider exported request ignored due to singleUser: "
4009 + p.className + " at " + mArchiveSourcePath + " "
4010 + parser.getPositionDescription());
4011 p.info.exported = false;
4012 }
4013 }
4014
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004015 p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
4016 R.styleable.AndroidManifestProvider_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004017 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004018 if (p.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004019 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004020 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004021 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004023 sa.recycle();
4024
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004025 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
4026 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004027 // A heavy-weight application can not have providers in its main process
4028 // We can do direct compare because we intern all strings.
4029 if (p.info.processName == owner.packageName) {
4030 outError[0] = "Heavy-weight applications can not have providers in main process";
4031 return null;
4032 }
4033 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004034
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004035 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07004036 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004037 return null;
4038 }
Dianne Hackborn1bc177c2014-12-03 10:20:30 -08004039 if (cpname.length() <= 0) {
4040 outError[0] = "<provider> has empty authorities attribute";
4041 return null;
4042 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004043 p.info.authority = cpname.intern();
4044
Svet Ganov354cd3c2015-12-17 11:35:04 -08004045 if (!parseProviderTags(res, parser, p, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004046 return null;
4047 }
4048
4049 return p;
4050 }
4051
4052 private boolean parseProviderTags(Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08004053 XmlResourceParser parser, Provider outInfo, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004054 throws XmlPullParserException, IOException {
4055 int outerDepth = parser.getDepth();
4056 int type;
4057 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4058 && (type != XmlPullParser.END_TAG
4059 || parser.getDepth() > outerDepth)) {
4060 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4061 continue;
4062 }
4063
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004064 if (parser.getName().equals("intent-filter")) {
4065 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
Svet Ganov354cd3c2015-12-17 11:35:04 -08004066 if (!parseIntent(res, parser, true, false, intent, outError)) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004067 return false;
4068 }
4069 outInfo.intents.add(intent);
4070
4071 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004072 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004073 outInfo.metaData, outError)) == null) {
4074 return false;
4075 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004077 } else if (parser.getName().equals("grant-uri-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004078 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004079 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
4080
4081 PatternMatcher pa = null;
4082
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004083 String str = sa.getNonConfigurationString(
4084 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004085 if (str != null) {
4086 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
4087 }
4088
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004089 str = sa.getNonConfigurationString(
4090 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004091 if (str != null) {
4092 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
4093 }
4094
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004095 str = sa.getNonConfigurationString(
4096 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 if (str != null) {
4098 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4099 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004101 sa.recycle();
4102
4103 if (pa != null) {
4104 if (outInfo.info.uriPermissionPatterns == null) {
4105 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
4106 outInfo.info.uriPermissionPatterns[0] = pa;
4107 } else {
4108 final int N = outInfo.info.uriPermissionPatterns.length;
4109 PatternMatcher[] newp = new PatternMatcher[N+1];
4110 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
4111 newp[N] = pa;
4112 outInfo.info.uriPermissionPatterns = newp;
4113 }
4114 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004115 } else {
4116 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004117 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004118 + parser.getName() + " at " + mArchiveSourcePath + " "
4119 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004120 XmlUtils.skipCurrentTag(parser);
4121 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004122 } else {
4123 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
4124 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004125 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004126 }
4127 XmlUtils.skipCurrentTag(parser);
4128
4129 } else if (parser.getName().equals("path-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004130 TypedArray sa = res.obtainAttributes(parser,
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004131 com.android.internal.R.styleable.AndroidManifestPathPermission);
4132
4133 PathPermission pa = null;
4134
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004135 String permission = sa.getNonConfigurationString(
4136 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
4137 String readPermission = sa.getNonConfigurationString(
4138 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004139 if (readPermission == null) {
4140 readPermission = permission;
4141 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004142 String writePermission = sa.getNonConfigurationString(
4143 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004144 if (writePermission == null) {
4145 writePermission = permission;
4146 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004147
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004148 boolean havePerm = false;
4149 if (readPermission != null) {
4150 readPermission = readPermission.intern();
4151 havePerm = true;
4152 }
4153 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00004154 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004155 havePerm = true;
4156 }
4157
4158 if (!havePerm) {
4159 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004160 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004161 + parser.getName() + " at " + mArchiveSourcePath + " "
4162 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004163 XmlUtils.skipCurrentTag(parser);
4164 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004165 } else {
4166 outError[0] = "No readPermission or writePermssion for <path-permission>";
4167 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004168 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004169 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004170
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004171 String path = sa.getNonConfigurationString(
4172 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004173 if (path != null) {
4174 pa = new PathPermission(path,
4175 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
4176 }
4177
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004178 path = sa.getNonConfigurationString(
4179 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004180 if (path != null) {
4181 pa = new PathPermission(path,
4182 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
4183 }
4184
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004185 path = sa.getNonConfigurationString(
4186 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004187 if (path != null) {
4188 pa = new PathPermission(path,
4189 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
4190 }
4191
4192 sa.recycle();
4193
4194 if (pa != null) {
4195 if (outInfo.info.pathPermissions == null) {
4196 outInfo.info.pathPermissions = new PathPermission[1];
4197 outInfo.info.pathPermissions[0] = pa;
4198 } else {
4199 final int N = outInfo.info.pathPermissions.length;
4200 PathPermission[] newp = new PathPermission[N+1];
4201 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
4202 newp[N] = pa;
4203 outInfo.info.pathPermissions = newp;
4204 }
4205 } else {
4206 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004207 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004208 + parser.getName() + " at " + mArchiveSourcePath + " "
4209 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004210 XmlUtils.skipCurrentTag(parser);
4211 continue;
4212 }
4213 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
4214 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004215 }
4216 XmlUtils.skipCurrentTag(parser);
4217
4218 } else {
4219 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004220 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004221 + parser.getName() + " at " + mArchiveSourcePath + " "
4222 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004223 XmlUtils.skipCurrentTag(parser);
4224 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004225 } else {
4226 outError[0] = "Bad element under <provider>: " + parser.getName();
4227 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004228 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004229 }
4230 }
4231 return true;
4232 }
4233
4234 private Service parseService(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08004235 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004236 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004237 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004238 com.android.internal.R.styleable.AndroidManifestService);
4239
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004240 if (mParseServiceArgs == null) {
4241 mParseServiceArgs = new ParseComponentArgs(owner, outError,
4242 com.android.internal.R.styleable.AndroidManifestService_name,
4243 com.android.internal.R.styleable.AndroidManifestService_label,
4244 com.android.internal.R.styleable.AndroidManifestService_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004245 com.android.internal.R.styleable.AndroidManifestService_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004246 com.android.internal.R.styleable.AndroidManifestService_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004247 com.android.internal.R.styleable.AndroidManifestService_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004248 mSeparateProcesses,
4249 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004250 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004251 com.android.internal.R.styleable.AndroidManifestService_enabled);
4252 mParseServiceArgs.tag = "<service>";
4253 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004254
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004255 mParseServiceArgs.sa = sa;
4256 mParseServiceArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004257
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004258 Service s = new Service(mParseServiceArgs, new ServiceInfo());
4259 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004260 sa.recycle();
4261 return null;
4262 }
4263
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004264 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004265 com.android.internal.R.styleable.AndroidManifestService_exported);
4266 if (setExported) {
4267 s.info.exported = sa.getBoolean(
4268 com.android.internal.R.styleable.AndroidManifestService_exported, false);
4269 }
4270
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004271 String str = sa.getNonConfigurationString(
4272 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004273 if (str == null) {
4274 s.info.permission = owner.applicationInfo.permission;
4275 } else {
4276 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
4277 }
4278
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004279 s.info.flags = 0;
4280 if (sa.getBoolean(
4281 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
4282 false)) {
4283 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
4284 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08004285 if (sa.getBoolean(
4286 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
4287 false)) {
4288 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
4289 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004290 if (sa.getBoolean(
Robert Sesekb9a86662015-12-09 16:22:45 -05004291 com.android.internal.R.styleable.AndroidManifestService_externalService,
4292 false)) {
4293 s.info.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE;
4294 }
4295 if (sa.getBoolean(
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004296 com.android.internal.R.styleable.AndroidManifestService_singleUser,
4297 false)) {
4298 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07004299 if (s.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004300 Slog.w(TAG, "Service exported request ignored due to singleUser: "
4301 + s.className + " at " + mArchiveSourcePath + " "
4302 + parser.getPositionDescription());
4303 s.info.exported = false;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07004304 setExported = true;
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004305 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004306 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004307
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004308 s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
4309 R.styleable.AndroidManifestService_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004310 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004311 if (s.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004312 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004313 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004314 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004316 sa.recycle();
4317
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004318 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
4319 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004320 // A heavy-weight application can not have services in its main process
4321 // We can do direct compare because we intern all strings.
4322 if (s.info.processName == owner.packageName) {
4323 outError[0] = "Heavy-weight applications can not have services in main process";
4324 return null;
4325 }
4326 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004328 int outerDepth = parser.getDepth();
4329 int type;
4330 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4331 && (type != XmlPullParser.END_TAG
4332 || parser.getDepth() > outerDepth)) {
4333 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4334 continue;
4335 }
4336
4337 if (parser.getName().equals("intent-filter")) {
4338 ServiceIntentInfo intent = new ServiceIntentInfo(s);
Svet Ganov354cd3c2015-12-17 11:35:04 -08004339 if (!parseIntent(res, parser, true, false, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004340 return null;
4341 }
4342
4343 s.intents.add(intent);
4344 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004345 if ((s.metaData=parseMetaData(res, parser, s.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004346 outError)) == null) {
4347 return null;
4348 }
4349 } else {
4350 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004351 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004352 + parser.getName() + " at " + mArchiveSourcePath + " "
4353 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004354 XmlUtils.skipCurrentTag(parser);
4355 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004356 } else {
4357 outError[0] = "Bad element under <service>: " + parser.getName();
4358 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004359 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004360 }
4361 }
4362
4363 if (!setExported) {
4364 s.info.exported = s.intents.size() > 0;
4365 }
4366
4367 return s;
4368 }
4369
Svet Ganov354cd3c2015-12-17 11:35:04 -08004370 private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag,
4371 Component<?> outInfo, String[] outError) throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004372 int outerDepth = parser.getDepth();
4373 int type;
4374 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4375 && (type != XmlPullParser.END_TAG
4376 || parser.getDepth() > outerDepth)) {
4377 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4378 continue;
4379 }
4380
4381 if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004382 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004383 outInfo.metaData, outError)) == null) {
4384 return false;
4385 }
4386 } else {
4387 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004388 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004389 + parser.getName() + " at " + mArchiveSourcePath + " "
4390 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004391 XmlUtils.skipCurrentTag(parser);
4392 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004393 } else {
4394 outError[0] = "Bad element under " + tag + ": " + parser.getName();
4395 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 }
4398 }
4399 return true;
4400 }
4401
4402 private Bundle parseMetaData(Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08004403 XmlResourceParser parser, Bundle data, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004404 throws XmlPullParserException, IOException {
4405
Svet Ganov354cd3c2015-12-17 11:35:04 -08004406 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004407 com.android.internal.R.styleable.AndroidManifestMetaData);
4408
4409 if (data == null) {
4410 data = new Bundle();
4411 }
4412
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004413 String name = sa.getNonConfigurationString(
4414 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004415 if (name == null) {
4416 outError[0] = "<meta-data> requires an android:name attribute";
4417 sa.recycle();
4418 return null;
4419 }
4420
Dianne Hackborn854060af2009-07-09 18:14:31 -07004421 name = name.intern();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004422
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004423 TypedValue v = sa.peekValue(
4424 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
4425 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004426 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004427 data.putInt(name, v.resourceId);
4428 } else {
4429 v = sa.peekValue(
4430 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07004431 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004432 if (v != null) {
4433 if (v.type == TypedValue.TYPE_STRING) {
4434 CharSequence cs = v.coerceToString();
Dianne Hackborn854060af2009-07-09 18:14:31 -07004435 data.putString(name, cs != null ? cs.toString().intern() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
4437 data.putBoolean(name, v.data != 0);
4438 } else if (v.type >= TypedValue.TYPE_FIRST_INT
4439 && v.type <= TypedValue.TYPE_LAST_INT) {
4440 data.putInt(name, v.data);
4441 } else if (v.type == TypedValue.TYPE_FLOAT) {
4442 data.putFloat(name, v.getFloat());
4443 } else {
4444 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004445 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004446 + parser.getName() + " at " + mArchiveSourcePath + " "
4447 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004448 } else {
4449 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
4450 data = null;
4451 }
4452 }
4453 } else {
4454 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
4455 data = null;
4456 }
4457 }
4458
4459 sa.recycle();
4460
4461 XmlUtils.skipCurrentTag(parser);
4462
4463 return data;
4464 }
4465
Kenny Root05ca4c92011-09-15 10:36:25 -07004466 private static VerifierInfo parseVerifier(Resources res, XmlPullParser parser,
Jeff Sharkey275e0852014-06-17 18:18:49 -07004467 AttributeSet attrs, int flags) {
Kenny Root05ca4c92011-09-15 10:36:25 -07004468 final TypedArray sa = res.obtainAttributes(attrs,
4469 com.android.internal.R.styleable.AndroidManifestPackageVerifier);
4470
4471 final String packageName = sa.getNonResourceString(
4472 com.android.internal.R.styleable.AndroidManifestPackageVerifier_name);
4473
4474 final String encodedPublicKey = sa.getNonResourceString(
4475 com.android.internal.R.styleable.AndroidManifestPackageVerifier_publicKey);
4476
4477 sa.recycle();
4478
4479 if (packageName == null || packageName.length() == 0) {
4480 Slog.i(TAG, "verifier package name was null; skipping");
4481 return null;
Kenny Root05ca4c92011-09-15 10:36:25 -07004482 }
4483
Christopher Tate30147332014-04-15 12:57:47 -07004484 final PublicKey publicKey = parsePublicKey(encodedPublicKey);
4485 if (publicKey == null) {
4486 Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
4487 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -08004488 }
4489
Christopher Tate30147332014-04-15 12:57:47 -07004490 return new VerifierInfo(packageName, publicKey);
Geremy Condraf1bcca82013-01-07 22:35:24 -08004491 }
4492
Christopher Tate30147332014-04-15 12:57:47 -07004493 public static final PublicKey parsePublicKey(final String encodedPublicKey) {
4494 if (encodedPublicKey == null) {
dcashman1616f302015-05-29 14:47:23 -07004495 Slog.w(TAG, "Could not parse null public key");
Christopher Tate30147332014-04-15 12:57:47 -07004496 return null;
4497 }
4498
Kenny Root05ca4c92011-09-15 10:36:25 -07004499 EncodedKeySpec keySpec;
4500 try {
4501 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
4502 keySpec = new X509EncodedKeySpec(encoded);
4503 } catch (IllegalArgumentException e) {
dcashman1616f302015-05-29 14:47:23 -07004504 Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07004505 return null;
4506 }
4507
4508 /* First try the key as an RSA key. */
4509 try {
4510 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08004511 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07004512 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07004513 Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07004514 } catch (InvalidKeySpecException e) {
4515 // Not a RSA public key.
4516 }
4517
dcashman1616f302015-05-29 14:47:23 -07004518 /* Now try it as a ECDSA key. */
4519 try {
4520 final KeyFactory keyFactory = KeyFactory.getInstance("EC");
4521 return keyFactory.generatePublic(keySpec);
4522 } catch (NoSuchAlgorithmException e) {
4523 Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build");
4524 } catch (InvalidKeySpecException e) {
4525 // Not a ECDSA public key.
4526 }
4527
Kenny Root05ca4c92011-09-15 10:36:25 -07004528 /* Now try it as a DSA key. */
4529 try {
4530 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08004531 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07004532 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07004533 Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07004534 } catch (InvalidKeySpecException e) {
4535 // Not a DSA public key.
4536 }
4537
dcashman1616f302015-05-29 14:47:23 -07004538 /* Not a supported key type */
Kenny Root05ca4c92011-09-15 10:36:25 -07004539 return null;
4540 }
4541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004542 private static final String ANDROID_RESOURCES
4543 = "http://schemas.android.com/apk/res/android";
4544
Svet Ganov354cd3c2015-12-17 11:35:04 -08004545 private boolean parseIntent(Resources res, XmlResourceParser parser,
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08004546 boolean allowGlobs, boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004547 throws XmlPullParserException, IOException {
4548
Svet Ganov354cd3c2015-12-17 11:35:04 -08004549 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004550 com.android.internal.R.styleable.AndroidManifestIntentFilter);
4551
4552 int priority = sa.getInt(
4553 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004554 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08004555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004556 TypedValue v = sa.peekValue(
4557 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
4558 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4559 outInfo.nonLocalizedLabel = v.coerceToString();
4560 }
4561
Todd Kennedya83bfca2016-06-03 07:52:17 -07004562 final boolean useRoundIcon =
4563 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
4564 int roundIconVal = useRoundIcon ? sa.getResourceId(
4565 com.android.internal.R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0;
4566 if (roundIconVal != 0) {
4567 outInfo.icon = roundIconVal;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004568 } else {
4569 outInfo.icon = sa.getResourceId(
4570 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
4571 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004572
Adam Powell81cd2e92010-04-21 16:35:18 -07004573 outInfo.logo = sa.getResourceId(
4574 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004575
Jose Limaf78e3122014-03-06 12:13:15 -08004576 outInfo.banner = sa.getResourceId(
4577 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
4578
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08004579 if (allowAutoVerify) {
4580 outInfo.setAutoVerify(sa.getBoolean(
4581 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
4582 false));
4583 }
4584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004585 sa.recycle();
4586
4587 int outerDepth = parser.getDepth();
4588 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07004589 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
4590 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
4591 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004592 continue;
4593 }
4594
4595 String nodeName = parser.getName();
4596 if (nodeName.equals("action")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004597 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004598 ANDROID_RESOURCES, "name");
4599 if (value == null || value == "") {
4600 outError[0] = "No value supplied for <android:name>";
4601 return false;
4602 }
4603 XmlUtils.skipCurrentTag(parser);
4604
4605 outInfo.addAction(value);
4606 } else if (nodeName.equals("category")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004607 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004608 ANDROID_RESOURCES, "name");
4609 if (value == null || value == "") {
4610 outError[0] = "No value supplied for <android:name>";
4611 return false;
4612 }
4613 XmlUtils.skipCurrentTag(parser);
4614
4615 outInfo.addCategory(value);
4616
4617 } else if (nodeName.equals("data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004618 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004619 com.android.internal.R.styleable.AndroidManifestData);
4620
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004621 String str = sa.getNonConfigurationString(
4622 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004623 if (str != null) {
4624 try {
4625 outInfo.addDataType(str);
4626 } catch (IntentFilter.MalformedMimeTypeException e) {
4627 outError[0] = e.toString();
4628 sa.recycle();
4629 return false;
4630 }
4631 }
4632
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004633 str = sa.getNonConfigurationString(
4634 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004635 if (str != null) {
4636 outInfo.addDataScheme(str);
4637 }
4638
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07004639 str = sa.getNonConfigurationString(
4640 com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
4641 if (str != null) {
4642 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
4643 }
4644
4645 str = sa.getNonConfigurationString(
4646 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
4647 if (str != null) {
4648 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
4649 }
4650
4651 str = sa.getNonConfigurationString(
4652 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
4653 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004654 if (!allowGlobs) {
4655 outError[0] = "sspPattern not allowed here; ssp must be literal";
4656 return false;
4657 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07004658 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4659 }
4660
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004661 String host = sa.getNonConfigurationString(
4662 com.android.internal.R.styleable.AndroidManifestData_host, 0);
4663 String port = sa.getNonConfigurationString(
4664 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004665 if (host != null) {
4666 outInfo.addDataAuthority(host, port);
4667 }
4668
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004669 str = sa.getNonConfigurationString(
4670 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004671 if (str != null) {
4672 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
4673 }
4674
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004675 str = sa.getNonConfigurationString(
4676 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004677 if (str != null) {
4678 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
4679 }
4680
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004681 str = sa.getNonConfigurationString(
4682 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004683 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004684 if (!allowGlobs) {
4685 outError[0] = "pathPattern not allowed here; path must be literal";
4686 return false;
4687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004688 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4689 }
4690
4691 sa.recycle();
4692 XmlUtils.skipCurrentTag(parser);
4693 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004694 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004695 + parser.getName() + " at " + mArchiveSourcePath + " "
4696 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004697 XmlUtils.skipCurrentTag(parser);
4698 } else {
4699 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
4700 return false;
4701 }
4702 }
4703
4704 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07004705
4706 if (DEBUG_PARSER) {
4707 final StringBuilder cats = new StringBuilder("Intent d=");
4708 cats.append(outInfo.hasDefault);
4709 cats.append(", cat=");
4710
4711 final Iterator<String> it = outInfo.categoriesIterator();
4712 if (it != null) {
4713 while (it.hasNext()) {
4714 cats.append(' ');
4715 cats.append(it.next());
4716 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004717 }
Kenny Rootd2d29252011-08-08 11:27:57 -07004718 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004719 }
4720
4721 return true;
4722 }
4723
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004724 /**
4725 * Representation of a full package parsed from APK files on disk. A package
4726 * consists of a single base APK, and zero or more split APKs.
4727 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004728 public final static class Package {
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07004729
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004730 public String packageName;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004731
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004732 /** Names of any split APKs, ordered by parsed splitName */
4733 public String[] splitNames;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004734
4735 // TODO: work towards making these paths invariant
Jeff Sharkey275e0852014-06-17 18:18:49 -07004736
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07004737 public String volumeUuid;
4738
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004739 /**
4740 * Path where this package was found on disk. For monolithic packages
4741 * this is path to single base APK file; for cluster packages this is
4742 * path to the cluster directory.
4743 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004744 public String codePath;
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004745
4746 /** Path of base APK */
4747 public String baseCodePath;
4748 /** Paths of any split APKs, ordered by parsed splitName */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004749 public String[] splitCodePaths;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004750
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004751 /** Revision code of base APK */
4752 public int baseRevisionCode;
4753 /** Revision codes of any split APKs, ordered by parsed splitName */
4754 public int[] splitRevisionCodes;
4755
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004756 /** Flags of any split APKs; ordered by parsed splitName */
4757 public int[] splitFlags;
4758
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004759 /**
4760 * Private flags of any split APKs; ordered by parsed splitName.
4761 *
4762 * {@hide}
4763 */
4764 public int[] splitPrivateFlags;
4765
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004766 public boolean baseHardwareAccelerated;
4767
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004768 // For now we only support one application per package.
4769 public final ApplicationInfo applicationInfo = new ApplicationInfo();
4770
4771 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
4772 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
4773 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
4774 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
4775 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
4776 public final ArrayList<Service> services = new ArrayList<Service>(0);
4777 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
4778
4779 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
4780
Dianne Hackborn854060af2009-07-09 18:14:31 -07004781 public ArrayList<String> protectedBroadcasts;
Dianne Hackbornc895be72013-03-11 17:48:43 -07004782
Svet Ganov354cd3c2015-12-17 11:35:04 -08004783 public Package parentPackage;
4784 public ArrayList<Package> childPackages;
4785
Dianne Hackbornc895be72013-03-11 17:48:43 -07004786 public ArrayList<String> libraryNames = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07004787 public ArrayList<String> usesLibraries = null;
4788 public ArrayList<String> usesOptionalLibraries = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004789 public String[] usesLibraryFiles = null;
4790
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004791 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
4792
Dianne Hackbornc1552392010-03-03 16:19:01 -08004793 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004794 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08004795 public ArrayList<String> mAdoptPermissions = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004797 // We store the application meta-data independently to avoid multiple unwanted references
4798 public Bundle mAppMetaData = null;
4799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004800 // The version code declared for this package.
4801 public int mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004803 // The version name declared for this package.
4804 public String mVersionName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004806 // The shared user id that this package wants to use.
4807 public String mSharedUserId;
4808
4809 // The shared user label that this package wants to use.
4810 public int mSharedUserLabel;
4811
4812 // Signatures that were read from the package.
Jeff Sharkey275e0852014-06-17 18:18:49 -07004813 public Signature[] mSignatures;
4814 public Certificate[][] mCertificates;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815
4816 // For use by package manager service for quick lookup of
4817 // preferred up order.
4818 public int mPreferredOrder = 0;
4819
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07004820 // For use by package manager to keep track of when a package was last used.
Brian Carlstromca82e612016-04-19 23:16:08 -07004821 public long[] mLastPackageUsageTimeInMills =
4822 new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07004823
Amith Yamasani13593602012-03-22 16:16:17 -07004824 // // User set enabled state.
4825 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
4826 //
4827 // // Whether the package has been stopped.
4828 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004830 // Additional data supplied by callers.
4831 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07004832
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004833 // Applications hardware preferences
4834 public ArrayList<ConfigurationInfo> configPreferences = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004836 // Applications requested features
Dianne Hackborn49237342009-08-27 20:08:01 -07004837 public ArrayList<FeatureInfo> reqFeatures = null;
4838
Adam Lesinskid3edfde2014-08-08 17:32:44 -07004839 // Applications requested feature groups
4840 public ArrayList<FeatureGroupInfo> featureGroups = null;
4841
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08004842 public int installLocation;
4843
Jeff Hao272bf3a2014-10-08 13:34:43 -07004844 public boolean coreApp;
4845
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08004846 /* An app that's required for all users and cannot be uninstalled for a user */
4847 public boolean mRequiredForAllUsers;
4848
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07004849 /* The restricted account authenticator type that is used by this application */
4850 public String mRestrictedAccountType;
4851
Amith Yamasaniccbe3892013-04-12 17:52:42 -07004852 /* The required account type without which this application will not function */
4853 public String mRequiredAccountType;
4854
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01004855 public String mOverlayTarget;
4856 public int mOverlayPriority;
4857 public boolean mTrustedOverlay;
4858
Geremy Condraf1bcca82013-01-07 22:35:24 -08004859 /**
dcashman989eb3712014-06-17 12:56:12 -07004860 * Data used to feed the KeySetManagerService
Geremy Condraf1bcca82013-01-07 22:35:24 -08004861 */
dcashman989eb3712014-06-17 12:56:12 -07004862 public ArraySet<PublicKey> mSigningKeys;
4863 public ArraySet<String> mUpgradeKeySets;
4864 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -08004865
Narayan Kamath4903f642014-08-11 13:33:45 +01004866 /**
4867 * The install time abi override for this package, if any.
4868 *
4869 * TODO: This seems like a horrible place to put the abiOverride because
4870 * this isn't something the packageParser parsers. However, this fits in with
4871 * the rest of the PackageManager where package scanning randomly pushes
4872 * and prods fields out of {@code this.applicationInfo}.
4873 */
4874 public String cpuAbiOverride;
Selim Gurun2d291d82016-02-05 17:50:53 -08004875 /**
4876 * The install time abi override to choose 32bit abi's when multiple abi's
4877 * are present. This is only meaningfull for multiarch applications.
4878 * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
4879 */
4880 public boolean use32bitAbi;
Narayan Kamath4903f642014-08-11 13:33:45 +01004881
Todd Kennedyfdd241a2016-04-28 12:26:53 -07004882 public byte[] restrictUpdateHash;
4883
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004884 public Package(String packageName) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07004885 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07004886 applicationInfo.packageName = packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004887 applicationInfo.uid = -1;
4888 }
4889
Svet Ganov354cd3c2015-12-17 11:35:04 -08004890 public void setApplicationVolumeUuid(String volumeUuid) {
4891 this.applicationInfo.volumeUuid = volumeUuid;
4892 if (childPackages != null) {
4893 final int packageCount = childPackages.size();
4894 for (int i = 0; i < packageCount; i++) {
4895 childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
4896 }
4897 }
4898 }
4899
4900 public void setApplicationInfoCodePath(String codePath) {
4901 this.applicationInfo.setCodePath(codePath);
4902 if (childPackages != null) {
4903 final int packageCount = childPackages.size();
4904 for (int i = 0; i < packageCount; i++) {
4905 childPackages.get(i).applicationInfo.setCodePath(codePath);
4906 }
4907 }
4908 }
4909
4910 public void setApplicationInfoResourcePath(String resourcePath) {
4911 this.applicationInfo.setResourcePath(resourcePath);
4912 if (childPackages != null) {
4913 final int packageCount = childPackages.size();
4914 for (int i = 0; i < packageCount; i++) {
4915 childPackages.get(i).applicationInfo.setResourcePath(resourcePath);
4916 }
4917 }
4918 }
4919
4920 public void setApplicationInfoBaseResourcePath(String resourcePath) {
4921 this.applicationInfo.setBaseResourcePath(resourcePath);
4922 if (childPackages != null) {
4923 final int packageCount = childPackages.size();
4924 for (int i = 0; i < packageCount; i++) {
4925 childPackages.get(i).applicationInfo.setBaseResourcePath(resourcePath);
4926 }
4927 }
4928 }
4929
4930 public void setApplicationInfoBaseCodePath(String baseCodePath) {
4931 this.applicationInfo.setBaseCodePath(baseCodePath);
4932 if (childPackages != null) {
4933 final int packageCount = childPackages.size();
4934 for (int i = 0; i < packageCount; i++) {
4935 childPackages.get(i).applicationInfo.setBaseCodePath(baseCodePath);
4936 }
4937 }
4938 }
4939
4940 public boolean hasChildPackage(String packageName) {
4941 final int childCount = (childPackages != null) ? childPackages.size() : 0;
4942 for (int i = 0; i < childCount; i++) {
4943 if (childPackages.get(i).packageName.equals(packageName)) {
4944 return true;
4945 }
4946 }
4947 return false;
4948 }
4949
4950 public void setApplicationInfoSplitCodePaths(String[] splitCodePaths) {
4951 this.applicationInfo.setSplitCodePaths(splitCodePaths);
4952 // Children have no splits
4953 }
4954
4955 public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) {
4956 this.applicationInfo.setSplitResourcePaths(resroucePaths);
4957 // Children have no splits
4958 }
4959
4960 public void setSplitCodePaths(String[] codePaths) {
4961 this.splitCodePaths = codePaths;
4962 }
4963
4964 public void setCodePath(String codePath) {
4965 this.codePath = codePath;
4966 if (childPackages != null) {
4967 final int packageCount = childPackages.size();
4968 for (int i = 0; i < packageCount; i++) {
4969 childPackages.get(i).codePath = codePath;
4970 }
4971 }
4972 }
4973
4974 public void setBaseCodePath(String baseCodePath) {
4975 this.baseCodePath = baseCodePath;
4976 if (childPackages != null) {
4977 final int packageCount = childPackages.size();
4978 for (int i = 0; i < packageCount; i++) {
4979 childPackages.get(i).baseCodePath = baseCodePath;
4980 }
4981 }
4982 }
4983
4984 public void setSignatures(Signature[] signatures) {
4985 this.mSignatures = signatures;
4986 if (childPackages != null) {
4987 final int packageCount = childPackages.size();
4988 for (int i = 0; i < packageCount; i++) {
4989 childPackages.get(i).mSignatures = signatures;
4990 }
4991 }
4992 }
4993
4994 public void setVolumeUuid(String volumeUuid) {
4995 this.volumeUuid = volumeUuid;
4996 if (childPackages != null) {
4997 final int packageCount = childPackages.size();
4998 for (int i = 0; i < packageCount; i++) {
4999 childPackages.get(i).volumeUuid = volumeUuid;
5000 }
5001 }
5002 }
5003
5004 public void setApplicationInfoFlags(int mask, int flags) {
5005 applicationInfo.flags = (applicationInfo.flags & ~mask) | (mask & flags);
5006 if (childPackages != null) {
5007 final int packageCount = childPackages.size();
5008 for (int i = 0; i < packageCount; i++) {
5009 childPackages.get(i).applicationInfo.flags =
5010 (applicationInfo.flags & ~mask) | (mask & flags);
5011 }
5012 }
5013 }
5014
Selim Gurun75827b22016-02-09 10:55:33 -08005015 public void setUse32bitAbi(boolean use32bitAbi) {
Selim Gurun2d291d82016-02-05 17:50:53 -08005016 this.use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08005017 if (childPackages != null) {
5018 final int packageCount = childPackages.size();
5019 for (int i = 0; i < packageCount; i++) {
Selim Gurun2d291d82016-02-05 17:50:53 -08005020 childPackages.get(i).use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08005021 }
5022 }
5023 }
5024
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005025 public List<String> getAllCodePaths() {
Jeff Sharkey275e0852014-06-17 18:18:49 -07005026 ArrayList<String> paths = new ArrayList<>();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005027 paths.add(baseCodePath);
Jeff Sharkey275e0852014-06-17 18:18:49 -07005028 if (!ArrayUtils.isEmpty(splitCodePaths)) {
5029 Collections.addAll(paths, splitCodePaths);
5030 }
5031 return paths;
5032 }
5033
Jeff Sharkeyda96e132014-07-15 14:54:09 -07005034 /**
5035 * Filtered set of {@link #getAllCodePaths()} that excludes
5036 * resource-only APKs.
5037 */
5038 public List<String> getAllCodePathsExcludingResourceOnly() {
5039 ArrayList<String> paths = new ArrayList<>();
5040 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
5041 paths.add(baseCodePath);
5042 }
5043 if (!ArrayUtils.isEmpty(splitCodePaths)) {
5044 for (int i = 0; i < splitCodePaths.length; i++) {
5045 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
5046 paths.add(splitCodePaths[i]);
5047 }
5048 }
5049 }
5050 return paths;
5051 }
5052
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005053 public void setPackageName(String newName) {
5054 packageName = newName;
5055 applicationInfo.packageName = newName;
5056 for (int i=permissions.size()-1; i>=0; i--) {
5057 permissions.get(i).setPackageName(newName);
5058 }
5059 for (int i=permissionGroups.size()-1; i>=0; i--) {
5060 permissionGroups.get(i).setPackageName(newName);
5061 }
5062 for (int i=activities.size()-1; i>=0; i--) {
5063 activities.get(i).setPackageName(newName);
5064 }
5065 for (int i=receivers.size()-1; i>=0; i--) {
5066 receivers.get(i).setPackageName(newName);
5067 }
5068 for (int i=providers.size()-1; i>=0; i--) {
5069 providers.get(i).setPackageName(newName);
5070 }
5071 for (int i=services.size()-1; i>=0; i--) {
5072 services.get(i).setPackageName(newName);
5073 }
5074 for (int i=instrumentation.size()-1; i>=0; i--) {
5075 instrumentation.get(i).setPackageName(newName);
5076 }
5077 }
Dianne Hackborn65696252012-03-05 18:49:21 -08005078
5079 public boolean hasComponentClassName(String name) {
5080 for (int i=activities.size()-1; i>=0; i--) {
5081 if (name.equals(activities.get(i).className)) {
5082 return true;
5083 }
5084 }
5085 for (int i=receivers.size()-1; i>=0; i--) {
5086 if (name.equals(receivers.get(i).className)) {
5087 return true;
5088 }
5089 }
5090 for (int i=providers.size()-1; i>=0; i--) {
5091 if (name.equals(providers.get(i).className)) {
5092 return true;
5093 }
5094 }
5095 for (int i=services.size()-1; i>=0; i--) {
5096 if (name.equals(services.get(i).className)) {
5097 return true;
5098 }
5099 }
5100 for (int i=instrumentation.size()-1; i>=0; i--) {
5101 if (name.equals(instrumentation.get(i).className)) {
5102 return true;
5103 }
5104 }
5105 return false;
5106 }
5107
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08005108 /**
5109 * @hide
5110 */
5111 public boolean isForwardLocked() {
5112 return applicationInfo.isForwardLocked();
5113 }
5114
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08005115 /**
5116 * @hide
5117 */
5118 public boolean isSystemApp() {
5119 return applicationInfo.isSystemApp();
5120 }
5121
5122 /**
5123 * @hide
5124 */
Svet Ganovadc1cf42015-06-15 16:36:24 -07005125 public boolean isPrivilegedApp() {
5126 return applicationInfo.isPrivilegedApp();
5127 }
5128
5129 /**
5130 * @hide
5131 */
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08005132 public boolean isUpdatedSystemApp() {
5133 return applicationInfo.isUpdatedSystemApp();
5134 }
5135
Fyodor Kupolovebcac162015-09-09 15:56:45 -07005136 /**
5137 * @hide
5138 */
5139 public boolean canHaveOatDir() {
5140 // The following app types CANNOT have oat directory
5141 // - non-updated system apps
5142 // - forward-locked apps or apps installed in ASEC containers
5143 return (!isSystemApp() || isUpdatedSystemApp())
5144 && !isForwardLocked() && !applicationInfo.isExternalAsec();
5145 }
5146
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07005147 public boolean isMatch(int flags) {
5148 if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
5149 return isSystemApp();
5150 }
5151 return true;
5152 }
5153
Brian Carlstromca82e612016-04-19 23:16:08 -07005154 public long getLatestPackageUseTimeInMills() {
5155 long latestUse = 0L;
5156 for (long use : mLastPackageUsageTimeInMills) {
5157 latestUse = Math.max(latestUse, use);
5158 }
5159 return latestUse;
5160 }
5161
David Brazdil90e26992016-04-18 14:08:52 +01005162 public long getLatestForegroundPackageUseTimeInMills() {
5163 int[] foregroundReasons = {
5164 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
5165 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
5166 };
5167
5168 long latestUse = 0L;
5169 for (int reason : foregroundReasons) {
5170 latestUse = Math.max(latestUse, mLastPackageUsageTimeInMills[reason]);
5171 }
5172 return latestUse;
5173 }
5174
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005175 public String toString() {
5176 return "Package{"
5177 + Integer.toHexString(System.identityHashCode(this))
5178 + " " + packageName + "}";
5179 }
5180 }
5181
5182 public static class Component<II extends IntentInfo> {
5183 public final Package owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005184 public final ArrayList<II> intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005185 public final String className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005186 public Bundle metaData;
5187
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005188 ComponentName componentName;
5189 String componentShortName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005191 public Component(Package _owner) {
5192 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005193 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005194 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005195 }
5196
5197 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
5198 owner = args.owner;
5199 intents = new ArrayList<II>(0);
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005200 if (parsePackageItemInfo(args.owner, outInfo, args.outError, args.tag, args.sa,
5201 true /*nameRequired*/, args.nameRes, args.labelRes, args.iconRes,
5202 args.roundIconRes, args.logoRes, args.bannerRes)) {
5203 className = outInfo.name;
5204 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005205 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005206 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005207 }
5208
5209 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
5210 this(args, (PackageItemInfo)outInfo);
5211 if (args.outError[0] != null) {
5212 return;
5213 }
5214
5215 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07005216 CharSequence pname;
5217 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07005218 pname = args.sa.getNonConfigurationString(args.processRes,
5219 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07005220 } else {
5221 // Some older apps have been seen to use a resource reference
5222 // here that on older builds was ignored (with a warning). We
5223 // need to continue to do this for them so they don't break.
5224 pname = args.sa.getNonResourceString(args.processRes);
5225 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005226 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07005227 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005228 args.flags, args.sepProcesses, args.outError);
5229 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005230
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005231 if (args.descriptionRes != 0) {
5232 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
5233 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005234
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005235 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005236 }
5237
5238 public Component(Component<II> clone) {
5239 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005240 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005241 className = clone.className;
5242 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005243 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005244 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005245
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005246 public ComponentName getComponentName() {
5247 if (componentName != null) {
5248 return componentName;
5249 }
5250 if (className != null) {
5251 componentName = new ComponentName(owner.applicationInfo.packageName,
5252 className);
5253 }
5254 return componentName;
5255 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005256
5257 public void appendComponentShortName(StringBuilder sb) {
5258 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005259 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005260
5261 public void printComponentShortName(PrintWriter pw) {
5262 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
5263 }
5264
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005265 public void setPackageName(String packageName) {
5266 componentName = null;
5267 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005268 }
5269 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005271 public final static class Permission extends Component<IntentInfo> {
5272 public final PermissionInfo info;
5273 public boolean tree;
5274 public PermissionGroup group;
5275
5276 public Permission(Package _owner) {
5277 super(_owner);
5278 info = new PermissionInfo();
5279 }
5280
5281 public Permission(Package _owner, PermissionInfo _info) {
5282 super(_owner);
5283 info = _info;
5284 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005285
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005286 public void setPackageName(String packageName) {
5287 super.setPackageName(packageName);
5288 info.packageName = packageName;
5289 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005290
5291 public String toString() {
5292 return "Permission{"
5293 + Integer.toHexString(System.identityHashCode(this))
5294 + " " + info.name + "}";
5295 }
5296 }
5297
5298 public final static class PermissionGroup extends Component<IntentInfo> {
5299 public final PermissionGroupInfo info;
5300
5301 public PermissionGroup(Package _owner) {
5302 super(_owner);
5303 info = new PermissionGroupInfo();
5304 }
5305
5306 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
5307 super(_owner);
5308 info = _info;
5309 }
5310
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005311 public void setPackageName(String packageName) {
5312 super.setPackageName(packageName);
5313 info.packageName = packageName;
5314 }
5315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005316 public String toString() {
5317 return "PermissionGroup{"
5318 + Integer.toHexString(System.identityHashCode(this))
5319 + " " + info.name + "}";
5320 }
5321 }
5322
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005323 private static boolean copyNeeded(int flags, Package p,
5324 PackageUserState state, Bundle metaData, int userId) {
Xiaohui Chen98404fd2015-08-17 16:09:02 -07005325 if (userId != UserHandle.USER_SYSTEM) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005326 // We always need to copy for other users, since we need
5327 // to fix up the uid.
5328 return true;
5329 }
5330 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
5331 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07005332 if (p.applicationInfo.enabled != enabled) {
5333 return true;
5334 }
5335 }
Rubin Xubf67c9c2016-04-20 17:09:38 +01005336 boolean suspended = (p.applicationInfo.flags & FLAG_SUSPENDED) != 0;
5337 if (state.suspended != suspended) {
5338 return true;
5339 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07005340 if (!state.installed || state.hidden) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005341 return true;
5342 }
5343 if (state.stopped) {
5344 return true;
5345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005346 if ((flags & PackageManager.GET_META_DATA) != 0
5347 && (metaData != null || p.mAppMetaData != null)) {
5348 return true;
5349 }
5350 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
5351 && p.usesLibraryFiles != null) {
5352 return true;
5353 }
5354 return false;
5355 }
5356
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005357 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
5358 PackageUserState state) {
5359 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07005360 }
5361
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08005362 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
5363 PackageUserState state) {
5364 // CompatibilityMode is global state.
5365 if (!sCompatibilityModeEnabled) {
5366 ai.disableCompatibilityMode();
5367 }
5368 if (state.installed) {
5369 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
5370 } else {
5371 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
5372 }
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00005373 if (state.suspended) {
5374 ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
5375 } else {
5376 ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
5377 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07005378 if (state.hidden) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005379 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07005380 } else {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005381 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07005382 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08005383 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
5384 ai.enabled = true;
5385 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
5386 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
5387 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
5388 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
5389 ai.enabled = false;
5390 }
5391 ai.enabledSetting = state.enabled;
5392 }
5393
Amith Yamasani13593602012-03-22 16:16:17 -07005394 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005395 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005396 if (p == null) return null;
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07005397 if (!checkUseInstalledOrHidden(flags, state) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005398 return null;
5399 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08005400 if (!copyNeeded(flags, p, state, null, userId)
5401 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
5402 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
5403 // In this case it is safe to directly modify the internal ApplicationInfo state:
5404 // - CompatibilityMode is global state, so will be the same for every call.
5405 // - We only come in to here if the app should reported as installed; this is the
5406 // default state, and we will do a copy otherwise.
5407 // - The enable state will always be reported the same for the application across
5408 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
5409 // be doing a copy.
5410 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005411 return p.applicationInfo;
5412 }
5413
5414 // Make shallow copy so we can store the metadata/libraries safely
5415 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Jeff Sharkey15447792015-11-05 16:18:51 -08005416 ai.initForUser(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005417 if ((flags & PackageManager.GET_META_DATA) != 0) {
5418 ai.metaData = p.mAppMetaData;
5419 }
5420 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
5421 ai.sharedLibraryFiles = p.usesLibraryFiles;
5422 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005423 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07005424 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08005425 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07005426 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08005427 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08005428 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005429 return ai;
5430 }
5431
Dianne Hackbornace27912014-09-18 18:38:30 -07005432 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
5433 PackageUserState state, int userId) {
5434 if (ai == null) return null;
5435 if (!checkUseInstalledOrHidden(flags, state)) {
5436 return null;
5437 }
5438 // This is only used to return the ResolverActivity; we will just always
5439 // make a copy.
5440 ai = new ApplicationInfo(ai);
Jeff Sharkey15447792015-11-05 16:18:51 -08005441 ai.initForUser(userId);
Dianne Hackbornace27912014-09-18 18:38:30 -07005442 if (state.stopped) {
5443 ai.flags |= ApplicationInfo.FLAG_STOPPED;
5444 } else {
5445 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
5446 }
5447 updateApplicationInfo(ai, flags, state);
5448 return ai;
5449 }
5450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005451 public static final PermissionInfo generatePermissionInfo(
5452 Permission p, int flags) {
5453 if (p == null) return null;
5454 if ((flags&PackageManager.GET_META_DATA) == 0) {
5455 return p.info;
5456 }
5457 PermissionInfo pi = new PermissionInfo(p.info);
5458 pi.metaData = p.metaData;
5459 return pi;
5460 }
5461
5462 public static final PermissionGroupInfo generatePermissionGroupInfo(
5463 PermissionGroup pg, int flags) {
5464 if (pg == null) return null;
5465 if ((flags&PackageManager.GET_META_DATA) == 0) {
5466 return pg.info;
5467 }
5468 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
5469 pgi.metaData = pg.metaData;
5470 return pgi;
5471 }
5472
5473 public final static class Activity extends Component<ActivityIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005474 public final ActivityInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005475
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005476 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
5477 super(args, _info);
5478 info = _info;
5479 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005480 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005481
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005482 public void setPackageName(String packageName) {
5483 super.setPackageName(packageName);
5484 info.packageName = packageName;
5485 }
5486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005487 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005488 StringBuilder sb = new StringBuilder(128);
5489 sb.append("Activity{");
5490 sb.append(Integer.toHexString(System.identityHashCode(this)));
5491 sb.append(' ');
5492 appendComponentShortName(sb);
5493 sb.append('}');
5494 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005495 }
5496 }
5497
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005498 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
5499 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005500 if (a == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07005501 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005502 return null;
5503 }
5504 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005505 return a.info;
5506 }
5507 // Make shallow copies so we can store the metadata safely
5508 ActivityInfo ai = new ActivityInfo(a.info);
5509 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005510 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005511 return ai;
5512 }
5513
Dianne Hackbornace27912014-09-18 18:38:30 -07005514 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
5515 PackageUserState state, int userId) {
5516 if (ai == null) return null;
5517 if (!checkUseInstalledOrHidden(flags, state)) {
5518 return null;
5519 }
5520 // This is only used to return the ResolverActivity; we will just always
5521 // make a copy.
5522 ai = new ActivityInfo(ai);
5523 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
5524 return ai;
5525 }
5526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005527 public final static class Service extends Component<ServiceIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005528 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005529
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005530 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
5531 super(args, _info);
5532 info = _info;
5533 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005534 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005535
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005536 public void setPackageName(String packageName) {
5537 super.setPackageName(packageName);
5538 info.packageName = packageName;
5539 }
5540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005541 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005542 StringBuilder sb = new StringBuilder(128);
5543 sb.append("Service{");
5544 sb.append(Integer.toHexString(System.identityHashCode(this)));
5545 sb.append(' ');
5546 appendComponentShortName(sb);
5547 sb.append('}');
5548 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005549 }
5550 }
5551
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005552 public static final ServiceInfo generateServiceInfo(Service s, int flags,
5553 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005554 if (s == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07005555 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005556 return null;
5557 }
5558 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005559 return s.info;
5560 }
5561 // Make shallow copies so we can store the metadata safely
5562 ServiceInfo si = new ServiceInfo(s.info);
5563 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005564 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005565 return si;
5566 }
5567
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005568 public final static class Provider extends Component<ProviderIntentInfo> {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005569 public final ProviderInfo info;
5570 public boolean syncable;
5571
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005572 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
5573 super(args, _info);
5574 info = _info;
5575 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005576 syncable = false;
5577 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005578
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005579 public Provider(Provider existingProvider) {
5580 super(existingProvider);
5581 this.info = existingProvider.info;
5582 this.syncable = existingProvider.syncable;
5583 }
5584
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005585 public void setPackageName(String packageName) {
5586 super.setPackageName(packageName);
5587 info.packageName = packageName;
5588 }
5589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005590 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005591 StringBuilder sb = new StringBuilder(128);
5592 sb.append("Provider{");
5593 sb.append(Integer.toHexString(System.identityHashCode(this)));
5594 sb.append(' ');
5595 appendComponentShortName(sb);
5596 sb.append('}');
5597 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005598 }
5599 }
5600
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005601 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
5602 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005603 if (p == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07005604 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005605 return null;
5606 }
5607 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005608 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005609 || p.info.uriPermissionPatterns == null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005610 return p.info;
5611 }
5612 // Make shallow copies so we can store the metadata safely
5613 ProviderInfo pi = new ProviderInfo(p.info);
5614 pi.metaData = p.metaData;
5615 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
5616 pi.uriPermissionPatterns = null;
5617 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005618 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005619 return pi;
5620 }
5621
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07005622 public final static class Instrumentation extends Component<IntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005623 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005624
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005625 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
5626 super(args, _info);
5627 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005628 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005629
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005630 public void setPackageName(String packageName) {
5631 super.setPackageName(packageName);
5632 info.packageName = packageName;
5633 }
5634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005635 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005636 StringBuilder sb = new StringBuilder(128);
5637 sb.append("Instrumentation{");
5638 sb.append(Integer.toHexString(System.identityHashCode(this)));
5639 sb.append(' ');
5640 appendComponentShortName(sb);
5641 sb.append('}');
5642 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005643 }
5644 }
5645
5646 public static final InstrumentationInfo generateInstrumentationInfo(
5647 Instrumentation i, int flags) {
5648 if (i == null) return null;
5649 if ((flags&PackageManager.GET_META_DATA) == 0) {
5650 return i.info;
5651 }
5652 InstrumentationInfo ii = new InstrumentationInfo(i.info);
5653 ii.metaData = i.metaData;
5654 return ii;
5655 }
5656
5657 public static class IntentInfo extends IntentFilter {
5658 public boolean hasDefault;
5659 public int labelRes;
5660 public CharSequence nonLocalizedLabel;
5661 public int icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07005662 public int logo;
Jose Limaf78e3122014-03-06 12:13:15 -08005663 public int banner;
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005664 public int preferred;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005665 }
5666
5667 public final static class ActivityIntentInfo extends IntentInfo {
5668 public final Activity activity;
5669
5670 public ActivityIntentInfo(Activity _activity) {
5671 activity = _activity;
5672 }
5673
5674 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005675 StringBuilder sb = new StringBuilder(128);
5676 sb.append("ActivityIntentInfo{");
5677 sb.append(Integer.toHexString(System.identityHashCode(this)));
5678 sb.append(' ');
5679 activity.appendComponentShortName(sb);
5680 sb.append('}');
5681 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005682 }
5683 }
5684
5685 public final static class ServiceIntentInfo extends IntentInfo {
5686 public final Service service;
5687
5688 public ServiceIntentInfo(Service _service) {
5689 service = _service;
5690 }
5691
5692 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005693 StringBuilder sb = new StringBuilder(128);
5694 sb.append("ServiceIntentInfo{");
5695 sb.append(Integer.toHexString(System.identityHashCode(this)));
5696 sb.append(' ');
5697 service.appendComponentShortName(sb);
5698 sb.append('}');
5699 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005700 }
5701 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005702
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005703 public static final class ProviderIntentInfo extends IntentInfo {
5704 public final Provider provider;
5705
5706 public ProviderIntentInfo(Provider provider) {
5707 this.provider = provider;
5708 }
5709
5710 public String toString() {
5711 StringBuilder sb = new StringBuilder(128);
5712 sb.append("ProviderIntentInfo{");
5713 sb.append(Integer.toHexString(System.identityHashCode(this)));
5714 sb.append(' ');
5715 provider.appendComponentShortName(sb);
5716 sb.append('}');
5717 return sb.toString();
5718 }
5719 }
5720
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005721 /**
5722 * @hide
5723 */
5724 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
5725 sCompatibilityModeEnabled = compatibilityModeEnabled;
5726 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005727
Jeff Sharkey275e0852014-06-17 18:18:49 -07005728 private static AtomicReference<byte[]> sBuffer = new AtomicReference<byte[]>();
5729
5730 public static long readFullyIgnoringContents(InputStream in) throws IOException {
5731 byte[] buffer = sBuffer.getAndSet(null);
5732 if (buffer == null) {
5733 buffer = new byte[4096];
5734 }
5735
5736 int n = 0;
5737 int count = 0;
5738 while ((n = in.read(buffer, 0, buffer.length)) != -1) {
5739 count += n;
5740 }
5741
5742 sBuffer.set(buffer);
5743 return count;
5744 }
5745
5746 public static void closeQuietly(StrictJarFile jarFile) {
5747 if (jarFile != null) {
5748 try {
5749 jarFile.close();
5750 } catch (Exception ignored) {
5751 }
5752 }
5753 }
5754
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005755 public static class PackageParserException extends Exception {
5756 public final int error;
5757
5758 public PackageParserException(int error, String detailMessage) {
5759 super(detailMessage);
5760 this.error = error;
5761 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07005762
5763 public PackageParserException(int error, String detailMessage, Throwable throwable) {
5764 super(detailMessage, throwable);
5765 this.error = error;
5766 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005767 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005768}