blob: 84605bb14d7da8668d6c17cb07a9c984d98c01d4 [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;
82import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
Wale Ogunwaled829d362016-02-10 19:24:49 -080083import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
Wale Ogunwaled26176f2016-01-25 20:04:04 -080084import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
85import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
86import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
87import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
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 Ganov354cd3c2015-12-17 11:35:04 -0800122 private static final int MAX_PACKAGES_PER_APK = 5;
123
Todd Kennedy66c55532016-02-26 16:22:11 -0800124 public static final int APK_SIGNING_UNKNOWN = 0;
125 public static final int APK_SIGNING_V1 = 1;
126 public static final int APK_SIGNING_V2 = 2;
127
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700128 // TODO: switch outError users to PackageParserException
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700129 // TODO: refactor "codePath" to "apkPath"
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700130
Kenny Rootbcc954d2011-08-08 16:19:08 -0700131 /** File name in an APK for the Android manifest. */
132 private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
133
Christopher Tatef3d939c2015-09-17 12:25:51 -0700134 /**
135 * File name in an APK for bytecode. There may be additional bytecode files
136 * but this one is always required for an APK that has code.
137 */
138 private static final String BYTECODE_FILENAME = "classes.dex";
139
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700140 /** Path prefix for apps on expanded storage */
141 private static final String MNT_EXPAND = "/mnt/expand/";
142
Svet Ganov354cd3c2015-12-17 11:35:04 -0800143 private static final String TAG_MANIFEST = "manifest";
144 private static final String TAG_APPLICATION = "application";
145 private static final String TAG_OVERLAY = "overlay";
146 private static final String TAG_KEY_SETS = "key-sets";
147 private static final String TAG_PERMISSION_GROUP = "permission-group";
148 private static final String TAG_PERMISSION = "permission";
149 private static final String TAG_PERMISSION_TREE = "permission-tree";
150 private static final String TAG_USES_PERMISSION = "uses-permission";
151 private static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
152 private static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23";
153 private static final String TAG_USES_CONFIGURATION = "uses-configuration";
154 private static final String TAG_USES_FEATURE = "uses-feature";
155 private static final String TAG_FEATURE_GROUP = "feature-group";
156 private static final String TAG_USES_SDK = "uses-sdk";
157 private static final String TAG_SUPPORT_SCREENS = "supports-screens";
158 private static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
159 private static final String TAG_INSTRUMENTATION = "instrumentation";
160 private static final String TAG_ORIGINAL_PACKAGE = "original-package";
161 private static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
162 private static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
163 private static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
164 private static final String TAG_SUPPORTS_INPUT = "supports-input";
165 private static final String TAG_EAT_COMMENT = "eat-comment";
166 private static final String TAG_PACKAGE = "package";
167
168 // These are the tags supported by child packages
169 private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>();
170 static {
171 CHILD_PACKAGE_TAGS.add(TAG_APPLICATION);
172 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION);
173 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_M);
174 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_23);
175 CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION);
176 CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE);
177 CHILD_PACKAGE_TAGS.add(TAG_FEATURE_GROUP);
178 CHILD_PACKAGE_TAGS.add(TAG_USES_SDK);
179 CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS);
180 CHILD_PACKAGE_TAGS.add(TAG_INSTRUMENTATION);
181 CHILD_PACKAGE_TAGS.add(TAG_USES_GL_TEXTURE);
182 CHILD_PACKAGE_TAGS.add(TAG_COMPATIBLE_SCREENS);
183 CHILD_PACKAGE_TAGS.add(TAG_SUPPORTS_INPUT);
184 CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
185 }
186
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700187 /** @hide */
188 public static class NewPermissionInfo {
189 public final String name;
190 public final int sdkVersion;
191 public final int fileVersion;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700192
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700193 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
194 this.name = name;
195 this.sdkVersion = sdkVersion;
196 this.fileVersion = fileVersion;
197 }
198 }
Dianne Hackborn79245122012-03-12 10:51:26 -0700199
200 /** @hide */
201 public static class SplitPermissionInfo {
202 public final String rootPerm;
203 public final String[] newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700204 public final int targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700205
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700206 public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
Dianne Hackborn79245122012-03-12 10:51:26 -0700207 this.rootPerm = rootPerm;
208 this.newPerms = newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700209 this.targetSdk = targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700210 }
211 }
212
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700213 /**
214 * List of new permissions that have been added since 1.0.
215 * NOTE: These must be declared in SDK version order, with permissions
216 * added to older SDKs appearing before those added to newer SDKs.
Dianne Hackborn79245122012-03-12 10:51:26 -0700217 * If sdkVersion is 0, then this is not a permission that we want to
218 * automatically add to older apps, but we do want to allow it to be
219 * granted during a platform update.
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700220 * @hide
221 */
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700222 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
223 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -0700224 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700225 android.os.Build.VERSION_CODES.DONUT, 0),
226 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
227 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700228 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229
Dianne Hackborn79245122012-03-12 10:51:26 -0700230 /**
231 * List of permissions that have been split into more granular or dependent
232 * permissions.
233 * @hide
234 */
235 public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
236 new PackageParser.SplitPermissionInfo[] {
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700237 // READ_EXTERNAL_STORAGE is always required when an app requests
238 // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
239 // write access without read access. The hack here with the target
240 // target SDK version ensures that this grant is always done.
Dianne Hackborn79245122012-03-12 10:51:26 -0700241 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700242 new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700243 android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700244 new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
245 new String[] { android.Manifest.permission.READ_CALL_LOG },
246 android.os.Build.VERSION_CODES.JELLY_BEAN),
247 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
248 new String[] { android.Manifest.permission.WRITE_CALL_LOG },
249 android.os.Build.VERSION_CODES.JELLY_BEAN)
Dianne Hackborn79245122012-03-12 10:51:26 -0700250 };
251
Jeff Sharkey275e0852014-06-17 18:18:49 -0700252 /**
253 * @deprecated callers should move to explicitly passing around source path.
254 */
255 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 private String mArchiveSourcePath;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700257
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700259 private boolean mOnlyCoreApps;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700260 private DisplayMetrics mMetrics;
261
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700262 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700263 private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264
265 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
266
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700267 private static boolean sCompatibilityModeEnabled = true;
Amith Yamasani655d0e22013-06-12 14:19:10 -0700268 private static final int PARSE_DEFAULT_INSTALL_LOCATION =
269 PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700270
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700271 static class ParsePackageItemArgs {
272 final Package owner;
273 final String[] outError;
274 final int nameRes;
275 final int labelRes;
276 final int iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700277 final int logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800278 final int bannerRes;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700279
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700280 String tag;
281 TypedArray sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700282
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700283 ParsePackageItemArgs(Package _owner, String[] _outError,
Jose Limaf78e3122014-03-06 12:13:15 -0800284 int _nameRes, int _labelRes, int _iconRes, int _logoRes, int _bannerRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700285 owner = _owner;
286 outError = _outError;
287 nameRes = _nameRes;
288 labelRes = _labelRes;
289 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700290 logoRes = _logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800291 bannerRes = _bannerRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700292 }
293 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700294
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700295 static class ParseComponentArgs extends ParsePackageItemArgs {
296 final String[] sepProcesses;
297 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800298 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700299 final int enabledRes;
300 int flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700301
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700302 ParseComponentArgs(Package _owner, String[] _outError,
Jose Limaf78e3122014-03-06 12:13:15 -0800303 int _nameRes, int _labelRes, int _iconRes, int _logoRes, int _bannerRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800304 String[] _sepProcesses, int _processRes,
305 int _descriptionRes, int _enabledRes) {
Jose Limaf78e3122014-03-06 12:13:15 -0800306 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _logoRes, _bannerRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700307 sepProcesses = _sepProcesses;
308 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800309 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700310 enabledRes = _enabledRes;
311 }
312 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800313
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700314 /**
Jeff Sharkey73767b92014-07-04 20:18:13 -0700315 * Lightweight parsed details about a single package.
316 */
317 public static class PackageLite {
318 public final String packageName;
319 public final int versionCode;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700320 public final int installLocation;
321 public final VerifierInfo[] verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700322
323 /** Names of any split APKs, ordered by parsed splitName */
324 public final String[] splitNames;
325
326 /**
327 * Path where this package was found on disk. For monolithic packages
328 * this is path to single base APK file; for cluster packages this is
329 * path to the cluster directory.
330 */
331 public final String codePath;
332
333 /** Path of base APK */
334 public final String baseCodePath;
335 /** Paths of any split APKs, ordered by parsed splitName */
336 public final String[] splitCodePaths;
337
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800338 /** Revision code of base APK */
339 public final int baseRevisionCode;
340 /** Revision codes of any split APKs, ordered by parsed splitName */
341 public final int[] splitRevisionCodes;
342
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700343 public final boolean coreApp;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100344 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800345 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700346 public final boolean extractNativeLibs;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100347
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700348 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800349 String[] splitCodePaths, int[] splitRevisionCodes) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700350 this.packageName = baseApk.packageName;
351 this.versionCode = baseApk.versionCode;
352 this.installLocation = baseApk.installLocation;
353 this.verifiers = baseApk.verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700354 this.splitNames = splitNames;
355 this.codePath = codePath;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700356 this.baseCodePath = baseApk.codePath;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700357 this.splitCodePaths = splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800358 this.baseRevisionCode = baseApk.revisionCode;
359 this.splitRevisionCodes = splitRevisionCodes;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700360 this.coreApp = baseApk.coreApp;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100361 this.multiArch = baseApk.multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800362 this.use32bitAbi = baseApk.use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700363 this.extractNativeLibs = baseApk.extractNativeLibs;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700364 }
365
366 public List<String> getAllCodePaths() {
367 ArrayList<String> paths = new ArrayList<>();
368 paths.add(baseCodePath);
369 if (!ArrayUtils.isEmpty(splitCodePaths)) {
370 Collections.addAll(paths, splitCodePaths);
371 }
372 return paths;
373 }
374 }
375
376 /**
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700377 * Lightweight parsed details about a single APK file.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800378 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700379 public static class ApkLite {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700380 public final String codePath;
Kenny Root05ca4c92011-09-15 10:36:25 -0700381 public final String packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700382 public final String splitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700383 public final int versionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800384 public final int revisionCode;
Kenny Root05ca4c92011-09-15 10:36:25 -0700385 public final int installLocation;
386 public final VerifierInfo[] verifiers;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700387 public final Signature[] signatures;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700388 public final boolean coreApp;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100389 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800390 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700391 public final boolean extractNativeLibs;
Kenny Root05ca4c92011-09-15 10:36:25 -0700392
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700393 public ApkLite(String codePath, String packageName, String splitName, int versionCode,
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800394 int revisionCode, int installLocation, List<VerifierInfo> verifiers,
Selim Gurun2d291d82016-02-05 17:50:53 -0800395 Signature[] signatures, boolean coreApp, boolean multiArch, boolean use32bitAbi,
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700396 boolean extractNativeLibs) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700397 this.codePath = codePath;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800398 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700399 this.splitName = splitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700400 this.versionCode = versionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800401 this.revisionCode = revisionCode;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800402 this.installLocation = installLocation;
Kenny Root05ca4c92011-09-15 10:36:25 -0700403 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700404 this.signatures = signatures;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700405 this.coreApp = coreApp;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100406 this.multiArch = multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800407 this.use32bitAbi = use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700408 this.extractNativeLibs = extractNativeLibs;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800409 }
410 }
411
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700412 private ParsePackageItemArgs mParseInstrumentationArgs;
413 private ParseComponentArgs mParseActivityArgs;
414 private ParseComponentArgs mParseActivityAliasArgs;
415 private ParseComponentArgs mParseServiceArgs;
416 private ParseComponentArgs mParseProviderArgs;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 /** If set to true, we will only allow package files that exactly match
419 * the DTD. Otherwise, we try to get as much from the package as we
420 * can without failing. This should normally be set to false, to
421 * support extensions to the DTD in future versions. */
422 private static final boolean RIGID_PARSER = false;
423
424 private static final String TAG = "PackageParser";
425
Jeff Sharkey275e0852014-06-17 18:18:49 -0700426 public PackageParser() {
427 mMetrics = new DisplayMetrics();
428 mMetrics.setToDefaults();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700429 }
430
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 public void setSeparateProcesses(String[] procs) {
432 mSeparateProcesses = procs;
433 }
434
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700435 /**
436 * Flag indicating this parser should only consider apps with
437 * {@code coreApp} manifest attribute to be valid apps. This is useful when
438 * creating a minimalist boot environment.
439 */
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700440 public void setOnlyCoreApps(boolean onlyCoreApps) {
441 mOnlyCoreApps = onlyCoreApps;
442 }
443
Jeff Sharkey275e0852014-06-17 18:18:49 -0700444 public void setDisplayMetrics(DisplayMetrics metrics) {
445 mMetrics = metrics;
446 }
447
Jeff Sharkey73767b92014-07-04 20:18:13 -0700448 public static final boolean isApkFile(File file) {
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700449 return isApkPath(file.getName());
450 }
451
452 private static boolean isApkPath(String path) {
453 return path.endsWith(".apk");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 }
455
456 /**
457 * Generate and return the {@link PackageInfo} for a parsed package.
458 *
459 * @param p the parsed package.
460 * @param flags indicating which optional information is included.
461 */
462 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Dianne Hackborne639da72012-02-21 15:11:13 -0800463 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svet Ganov3695b8a2015-03-24 16:30:25 -0700464 Set<String> grantedPermissions, PackageUserState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465
Amith Yamasani483f3b02012-03-13 16:08:00 -0700466 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700467 grantedPermissions, state, UserHandle.getCallingUserId());
468 }
469
Amith Yamasani655d0e22013-06-12 14:19:10 -0700470 /**
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700471 * Returns true if the package is installed and not hidden, or if the caller
472 * explicitly wanted all uninstalled and hidden packages as well.
Amith Yamasani655d0e22013-06-12 14:19:10 -0700473 */
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700474 private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state) {
475 return (state.installed && !state.hidden)
Amith Yamasani655d0e22013-06-12 14:19:10 -0700476 || (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700477 }
478
Christopher Tateba629da2013-11-13 17:42:28 -0800479 public static boolean isAvailable(PackageUserState state) {
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700480 return checkUseInstalledOrHidden(0, state);
Christopher Tateba629da2013-11-13 17:42:28 -0800481 }
482
Amith Yamasani13593602012-03-22 16:16:17 -0700483 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Amith Yamasani483f3b02012-03-13 16:08:00 -0700484 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svetoslavc6d1c342015-02-26 14:44:43 -0800485 Set<String> grantedPermissions, PackageUserState state, int userId) {
Jeff Sharkeyc5967e92016-01-07 18:50:29 -0700486 if (!checkUseInstalledOrHidden(flags, state) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700487 return null;
488 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 PackageInfo pi = new PackageInfo();
490 pi.packageName = p.packageName;
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700491 pi.splitNames = p.splitNames;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800492 pi.versionCode = p.mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800493 pi.baseRevisionCode = p.baseRevisionCode;
494 pi.splitRevisionCodes = p.splitRevisionCodes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 pi.versionName = p.mVersionName;
496 pi.sharedUserId = p.mSharedUserId;
497 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700498 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800499 pi.installLocation = p.installLocation;
Jeff Hao272bf3a2014-10-08 13:34:43 -0700500 pi.coreApp = p.coreApp;
Amith Yamasani0d8750d2013-05-01 15:25:28 -0700501 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
502 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
503 pi.requiredForAllUsers = p.mRequiredForAllUsers;
504 }
Amith Yamasani0ac1fc92013-03-27 18:56:08 -0700505 pi.restrictedAccountType = p.mRestrictedAccountType;
Amith Yamasaniccbe3892013-04-12 17:52:42 -0700506 pi.requiredAccountType = p.mRequiredAccountType;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100507 pi.overlayTarget = p.mOverlayTarget;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700508 pi.firstInstallTime = firstInstallTime;
509 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 if ((flags&PackageManager.GET_GIDS) != 0) {
511 pi.gids = gids;
512 }
513 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700514 int N = p.configPreferences != null ? p.configPreferences.size() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800515 if (N > 0) {
516 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700517 p.configPreferences.toArray(pi.configPreferences);
518 }
519 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
520 if (N > 0) {
521 pi.reqFeatures = new FeatureInfo[N];
522 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 }
Adam Lesinskid3edfde2014-08-08 17:32:44 -0700524 N = p.featureGroups != null ? p.featureGroups.size() : 0;
525 if (N > 0) {
526 pi.featureGroups = new FeatureGroupInfo[N];
527 p.featureGroups.toArray(pi.featureGroups);
528 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700530 if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
531 final int N = p.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700533 int num = 0;
534 final ActivityInfo[] res = new ActivityInfo[N];
535 for (int i = 0; i < N; i++) {
536 final Activity a = p.activities.get(i);
537 if (state.isMatch(a.info, flags)) {
538 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800539 }
540 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700541 pi.activities = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 }
543 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700544 if ((flags & PackageManager.GET_RECEIVERS) != 0) {
545 final int N = p.receivers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700547 int num = 0;
548 final ActivityInfo[] res = new ActivityInfo[N];
549 for (int i = 0; i < N; i++) {
550 final Activity a = p.receivers.get(i);
551 if (state.isMatch(a.info, flags)) {
552 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553 }
554 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700555 pi.receivers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 }
557 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700558 if ((flags & PackageManager.GET_SERVICES) != 0) {
559 final int N = p.services.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800560 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700561 int num = 0;
562 final ServiceInfo[] res = new ServiceInfo[N];
563 for (int i = 0; i < N; i++) {
564 final Service s = p.services.get(i);
565 if (state.isMatch(s.info, flags)) {
566 res[num++] = generateServiceInfo(s, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800567 }
568 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700569 pi.services = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 }
571 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700572 if ((flags & PackageManager.GET_PROVIDERS) != 0) {
573 final int N = p.providers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800574 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700575 int num = 0;
576 final ProviderInfo[] res = new ProviderInfo[N];
577 for (int i = 0; i < N; i++) {
578 final Provider pr = p.providers.get(i);
579 if (state.isMatch(pr.info, flags)) {
580 res[num++] = generateProviderInfo(pr, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581 }
582 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700583 pi.providers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800584 }
585 }
586 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
587 int N = p.instrumentation.size();
588 if (N > 0) {
589 pi.instrumentation = new InstrumentationInfo[N];
590 for (int i=0; i<N; i++) {
591 pi.instrumentation[i] = generateInstrumentationInfo(
592 p.instrumentation.get(i), flags);
593 }
594 }
595 }
596 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
597 int N = p.permissions.size();
598 if (N > 0) {
599 pi.permissions = new PermissionInfo[N];
600 for (int i=0; i<N; i++) {
601 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
602 }
603 }
604 N = p.requestedPermissions.size();
605 if (N > 0) {
606 pi.requestedPermissions = new String[N];
Dianne Hackborne639da72012-02-21 15:11:13 -0800607 pi.requestedPermissionsFlags = new int[N];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608 for (int i=0; i<N; i++) {
Dianne Hackborne639da72012-02-21 15:11:13 -0800609 final String perm = p.requestedPermissions.get(i);
610 pi.requestedPermissions[i] = perm;
Svet Ganov3695b8a2015-03-24 16:30:25 -0700611 // The notion of required permissions is deprecated but for compatibility.
Svetoslavc6d1c342015-02-26 14:44:43 -0800612 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800613 if (grantedPermissions != null && grantedPermissions.contains(perm)) {
614 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
615 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 }
617 }
618 }
619 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700620 int N = (p.mSignatures != null) ? p.mSignatures.length : 0;
621 if (N > 0) {
622 pi.signatures = new Signature[N];
623 System.arraycopy(p.mSignatures, 0, pi.signatures, 0, N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624 }
625 }
626 return pi;
627 }
628
Jeff Sharkey275e0852014-06-17 18:18:49 -0700629 private static Certificate[][] loadCertificates(StrictJarFile jarFile, ZipEntry entry)
630 throws PackageParserException {
631 InputStream is = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632 try {
633 // We must read the stream for the JarEntry to retrieve
634 // its certificates.
Jeff Sharkey275e0852014-06-17 18:18:49 -0700635 is = jarFile.getInputStream(entry);
636 readFullyIgnoringContents(is);
637 return jarFile.getCertificateChains(entry);
638 } catch (IOException | RuntimeException e) {
639 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
640 "Failed reading " + entry.getName() + " in " + jarFile, e);
641 } finally {
642 IoUtils.closeQuietly(is);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800644 }
645
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800646 public final static int PARSE_IS_SYSTEM = 1<<0;
647 public final static int PARSE_CHATTY = 1<<1;
648 public final static int PARSE_MUST_BE_APK = 1<<2;
649 public final static int PARSE_IGNORE_PROCESSES = 1<<3;
650 public final static int PARSE_FORWARD_LOCK = 1<<4;
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -0700651 public final static int PARSE_EXTERNAL_STORAGE = 1<<5;
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700652 public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
Christopher Tateccbf84f2013-05-08 15:25:41 -0700653 public final static int PARSE_IS_PRIVILEGED = 1<<7;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700654 public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700655 public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
Christopher Tatef3d939c2015-09-17 12:25:51 -0700656 public final static int PARSE_ENFORCE_CODE = 1<<10;
Todd Kennedy373f0b42015-12-16 14:45:14 -0800657 public final static int PARSE_IS_EPHEMERAL = 1<<11;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700658
659 private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800660
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700661 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700662 * Used to sort a set of APKs based on their split names, always placing the
663 * base APK (with {@code null} split name) first.
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700664 */
Jeff Sharkey275e0852014-06-17 18:18:49 -0700665 private static class SplitNameComparator implements Comparator<String> {
666 @Override
667 public int compare(String lhs, String rhs) {
668 if (lhs == null) {
669 return -1;
670 } else if (rhs == null) {
671 return 1;
672 } else {
673 return lhs.compareTo(rhs);
674 }
675 }
676 }
677
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700678 /**
679 * Parse only lightweight details about the package at the given location.
680 * Automatically detects if the package is a monolithic style (single APK
681 * file) or cluster style (directory of APKs).
682 * <p>
683 * This performs sanity checking on cluster style packages, such as
684 * requiring identical package name and version codes, a single base APK,
685 * and unique split names.
686 *
687 * @see PackageParser#parsePackage(File, int)
688 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700689 public static PackageLite parsePackageLite(File packageFile, int flags)
690 throws PackageParserException {
691 if (packageFile.isDirectory()) {
692 return parseClusterPackageLite(packageFile, flags);
693 } else {
694 return parseMonolithicPackageLite(packageFile, flags);
695 }
696 }
697
698 private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
699 throws PackageParserException {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700700 final ApkLite baseApk = parseApkLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700701 final String packagePath = packageFile.getAbsolutePath();
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800702 return new PackageLite(packagePath, baseApk, null, null, null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700703 }
704
705 private static PackageLite parseClusterPackageLite(File packageDir, int flags)
706 throws PackageParserException {
707 final File[] files = packageDir.listFiles();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700708 if (ArrayUtils.isEmpty(files)) {
709 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
710 "No packages found in split");
711 }
712
Jeff Sharkey275e0852014-06-17 18:18:49 -0700713 String packageName = null;
714 int versionCode = 0;
715
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700716 final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700717 for (File file : files) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700718 if (isApkFile(file)) {
719 final ApkLite lite = parseApkLite(file, flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -0700720
721 // Assert that all package names and version codes are
722 // consistent with the first one we encounter.
723 if (packageName == null) {
724 packageName = lite.packageName;
725 versionCode = lite.versionCode;
726 } else {
727 if (!packageName.equals(lite.packageName)) {
728 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
729 "Inconsistent package " + lite.packageName + " in " + file
730 + "; expected " + packageName);
731 }
732 if (versionCode != lite.versionCode) {
733 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
734 "Inconsistent version " + lite.versionCode + " in " + file
735 + "; expected " + versionCode);
736 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700737 }
738
Jeff Sharkey275e0852014-06-17 18:18:49 -0700739 // Assert that each split is defined only once
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700740 if (apks.put(lite.splitName, lite) != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700741 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
742 "Split name " + lite.splitName
743 + " defined more than once; most recent was " + file);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700744 }
745 }
746 }
747
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700748 final ApkLite baseApk = apks.remove(null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700749 if (baseApk == null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700750 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
Jeff Sharkey73767b92014-07-04 20:18:13 -0700751 "Missing base APK in " + packageDir);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700752 }
753
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700754 // Always apply deterministic ordering based on splitName
755 final int size = apks.size();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700756
Jeff Sharkey73767b92014-07-04 20:18:13 -0700757 String[] splitNames = null;
758 String[] splitCodePaths = null;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800759 int[] splitRevisionCodes = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700760 if (size > 0) {
761 splitNames = new String[size];
762 splitCodePaths = new String[size];
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800763 splitRevisionCodes = new int[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700764
765 splitNames = apks.keySet().toArray(splitNames);
766 Arrays.sort(splitNames, sSplitNameComparator);
767
768 for (int i = 0; i < size; i++) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700769 splitCodePaths[i] = apks.get(splitNames[i]).codePath;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800770 splitRevisionCodes[i] = apks.get(splitNames[i]).revisionCode;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700771 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700772 }
773
Jeff Sharkey73767b92014-07-04 20:18:13 -0700774 final String codePath = packageDir.getAbsolutePath();
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800775 return new PackageLite(codePath, baseApk, splitNames, splitCodePaths,
776 splitRevisionCodes);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700777 }
778
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700779 /**
780 * Parse the package at the given location. Automatically detects if the
781 * package is a monolithic style (single APK file) or cluster style
782 * (directory of APKs).
783 * <p>
784 * This performs sanity checking on cluster style packages, such as
785 * requiring identical package name and version codes, a single base APK,
786 * and unique split names.
787 * <p>
788 * Note that this <em>does not</em> perform signature verification; that
789 * must be done separately in {@link #collectCertificates(Package, int)}.
790 *
791 * @see #parsePackageLite(File, int)
792 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700793 public Package parsePackage(File packageFile, int flags) throws PackageParserException {
794 if (packageFile.isDirectory()) {
795 return parseClusterPackage(packageFile, flags);
796 } else {
797 return parseMonolithicPackage(packageFile, flags);
798 }
799 }
800
801 /**
802 * Parse all APKs contained in the given directory, treating them as a
803 * single package. This also performs sanity checking, such as requiring
804 * identical package name and version codes, a single base APK, and unique
805 * split names.
806 * <p>
807 * Note that this <em>does not</em> perform signature verification; that
808 * must be done separately in {@link #collectCertificates(Package, int)}.
809 */
810 private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
811 final PackageLite lite = parseClusterPackageLite(packageDir, 0);
812
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700813 if (mOnlyCoreApps && !lite.coreApp) {
814 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
815 "Not a coreApp: " + packageDir);
816 }
817
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700818 final AssetManager assets = new AssetManager();
819 try {
820 // Load the base and all splits into the AssetManager
821 // so that resources can be overriden when parsing the manifests.
822 loadApkIntoAssetManager(assets, lite.baseCodePath, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700823
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700824 if (!ArrayUtils.isEmpty(lite.splitCodePaths)) {
825 for (String path : lite.splitCodePaths) {
826 loadApkIntoAssetManager(assets, path, flags);
827 }
Jeff Sharkey73767b92014-07-04 20:18:13 -0700828 }
Jeff Sharkey73767b92014-07-04 20:18:13 -0700829
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700830 final File baseApk = new File(lite.baseCodePath);
831 final Package pkg = parseBaseApk(baseApk, assets, flags);
832 if (pkg == null) {
833 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
834 "Failed to parse base APK: " + baseApk);
835 }
836
837 if (!ArrayUtils.isEmpty(lite.splitNames)) {
838 final int num = lite.splitNames.length;
839 pkg.splitNames = lite.splitNames;
840 pkg.splitCodePaths = lite.splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800841 pkg.splitRevisionCodes = lite.splitRevisionCodes;
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700842 pkg.splitFlags = new int[num];
Alex Klyubinb9f8a522015-02-03 11:12:59 -0800843 pkg.splitPrivateFlags = new int[num];
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700844
845 for (int i = 0; i < num; i++) {
846 parseSplitApk(pkg, i, assets, flags);
847 }
848 }
849
Svet Ganov354cd3c2015-12-17 11:35:04 -0800850 pkg.setCodePath(packageDir.getAbsolutePath());
Selim Gurun2d291d82016-02-05 17:50:53 -0800851 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700852 return pkg;
853 } finally {
854 IoUtils.closeQuietly(assets);
855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856 }
857
Jeff Sharkey275e0852014-06-17 18:18:49 -0700858 /**
859 * Parse the given APK file, treating it as as a single monolithic package.
860 * <p>
861 * Note that this <em>does not</em> perform signature verification; that
862 * must be done separately in {@link #collectCertificates(Package, int)}.
Jeff Sharkeyd7460572014-07-06 20:44:55 -0700863 *
864 * @deprecated external callers should move to
865 * {@link #parsePackage(File, int)}. Eventually this method will
866 * be marked private.
Jeff Sharkey275e0852014-06-17 18:18:49 -0700867 */
Jeff Sharkeyd7460572014-07-06 20:44:55 -0700868 @Deprecated
Jeff Sharkey275e0852014-06-17 18:18:49 -0700869 public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
Tao Baic9a02372016-01-12 15:02:24 -0800870 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700871 if (mOnlyCoreApps) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700872 if (!lite.coreApp) {
873 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
874 "Not a coreApp: " + apkFile);
875 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700876 }
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700877
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700878 final AssetManager assets = new AssetManager();
879 try {
880 final Package pkg = parseBaseApk(apkFile, assets, flags);
Svet Ganov354cd3c2015-12-17 11:35:04 -0800881 pkg.setCodePath(apkFile.getAbsolutePath());
Selim Gurun2d291d82016-02-05 17:50:53 -0800882 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700883 return pkg;
884 } finally {
885 IoUtils.closeQuietly(assets);
886 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700887 }
888
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700889 private static int loadApkIntoAssetManager(AssetManager assets, String apkPath, int flags)
890 throws PackageParserException {
891 if ((flags & PARSE_MUST_BE_APK) != 0 && !isApkPath(apkPath)) {
892 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
893 "Invalid package file: " + apkPath);
894 }
895
896 // The AssetManager guarantees uniqueness for asset paths, so if this asset path
897 // already exists in the AssetManager, addAssetPath will only return the cookie
898 // assigned to it.
899 int cookie = assets.addAssetPath(apkPath);
900 if (cookie == 0) {
901 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
902 "Failed adding asset path: " + apkPath);
903 }
904 return cookie;
905 }
906
907 private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
908 throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700909 final String apkPath = apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -0700910
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700911 String volumeUuid = null;
912 if (apkPath.startsWith(MNT_EXPAND)) {
913 final int end = apkPath.indexOf('/', MNT_EXPAND.length());
914 volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
915 }
916
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917 mParseError = PackageManager.INSTALL_SUCCEEDED;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700918 mArchiveSourcePath = apkFile.getAbsolutePath();
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700919
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700920 if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700922 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
923
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800924 Resources res = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700925 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700927 res = new Resources(assets, mMetrics, null);
928 assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
929 Build.VERSION.RESOURCES_SDK_INT);
930 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
931
932 final String[] outError = new String[1];
933 final Package pkg = parseBaseApk(res, parser, flags, outError);
934 if (pkg == null) {
935 throw new PackageParserException(mParseError,
936 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800937 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700938
Svet Ganov354cd3c2015-12-17 11:35:04 -0800939 pkg.setVolumeUuid(volumeUuid);
940 pkg.setApplicationVolumeUuid(volumeUuid);
941 pkg.setBaseCodePath(apkPath);
942 pkg.setSignatures(null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700943
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700944 return pkg;
945
946 } catch (PackageParserException e) {
947 throw e;
948 } catch (Exception e) {
949 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -0700950 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700951 } finally {
952 IoUtils.closeQuietly(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 }
955
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700956 private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700957 throws PackageParserException {
958 final String apkPath = pkg.splitCodePaths[splitIndex];
Jeff Sharkey275e0852014-06-17 18:18:49 -0700959
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700960 mParseError = PackageManager.INSTALL_SUCCEEDED;
961 mArchiveSourcePath = apkPath;
962
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700963 if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
964
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700965 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
966
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700967 Resources res = null;
968 XmlResourceParser parser = null;
969 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700970 res = new Resources(assets, mMetrics, null);
971 assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
972 Build.VERSION.RESOURCES_SDK_INT);
973 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
974
975 final String[] outError = new String[1];
976 pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
977 if (pkg == null) {
978 throw new PackageParserException(mParseError,
979 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
980 }
981
982 } catch (PackageParserException e) {
983 throw e;
984 } catch (Exception e) {
985 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -0700986 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700987 } finally {
988 IoUtils.closeQuietly(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700989 }
990 }
991
992 /**
993 * Parse the manifest of a <em>split APK</em>.
994 * <p>
995 * Note that split APKs have many more restrictions on what they're capable
996 * of doing, so many valid features of a base APK have been carefully
997 * omitted here.
998 */
999 private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001000 int splitIndex, String[] outError) throws XmlPullParserException, IOException,
1001 PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001002 AttributeSet attrs = parser;
1003
Jeff Sharkey78a13012014-07-15 20:18:34 -07001004 // We parsed manifest tag earlier; just skip past it
Svet Ganov354cd3c2015-12-17 11:35:04 -08001005 parsePackageSplitNames(parser, attrs);
Jeff Sharkey78a13012014-07-15 20:18:34 -07001006
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001007 mParseInstrumentationArgs = null;
1008 mParseActivityArgs = null;
1009 mParseServiceArgs = null;
1010 mParseProviderArgs = null;
1011
1012 int type;
1013
1014 boolean foundApp = false;
1015
1016 int outerDepth = parser.getDepth();
1017 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1018 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1019 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1020 continue;
1021 }
1022
1023 String tagName = parser.getName();
1024 if (tagName.equals("application")) {
1025 if (foundApp) {
1026 if (RIGID_PARSER) {
1027 outError[0] = "<manifest> has more than one <application>";
1028 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1029 return null;
1030 } else {
1031 Slog.w(TAG, "<manifest> has more than one <application>");
1032 XmlUtils.skipCurrentTag(parser);
1033 continue;
1034 }
1035 }
1036
1037 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001038 if (!parseSplitApplication(pkg, res, parser, flags, splitIndex, outError)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001039 return null;
1040 }
1041
1042 } else if (RIGID_PARSER) {
1043 outError[0] = "Bad element under <manifest>: "
1044 + parser.getName();
1045 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1046 return null;
1047
1048 } else {
1049 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1050 + " at " + mArchiveSourcePath + " "
1051 + parser.getPositionDescription());
1052 XmlUtils.skipCurrentTag(parser);
1053 continue;
1054 }
1055 }
1056
1057 if (!foundApp) {
1058 outError[0] = "<manifest> does not contain an <application>";
1059 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1060 }
1061
1062 return pkg;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001063 }
1064
Todd Kennedy66c55532016-02-26 16:22:11 -08001065 public static int getApkSigningVersion(Package pkg) {
1066 try {
1067 if (ApkSignatureSchemeV2Verifier.hasSignature(pkg.baseCodePath)) {
1068 return APK_SIGNING_V2;
1069 }
1070 return APK_SIGNING_V1;
1071 } catch (IOException e) {
1072 }
1073 return APK_SIGNING_UNKNOWN;
1074 }
1075
Kenny Root6c918ce2013-04-02 14:04:24 -07001076 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -07001077 * Collect certificates from all the APKs described in the given package,
Todd Kennedy373f0b42015-12-16 14:45:14 -08001078 * populating {@link Package#mSignatures}. Also asserts that all APK
Jeff Sharkey275e0852014-06-17 18:18:49 -07001079 * contents are signed correctly and consistently.
1080 */
Todd Kennedy66c55532016-02-26 16:22:11 -08001081 public static void collectCertificates(Package pkg, int parseFlags)
1082 throws PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001083 collectCertificatesInternal(pkg, parseFlags);
1084 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1085 for (int i = 0; i < childCount; i++) {
1086 Package childPkg = pkg.childPackages.get(i);
1087 childPkg.mCertificates = pkg.mCertificates;
1088 childPkg.mSignatures = pkg.mSignatures;
1089 childPkg.mSigningKeys = pkg.mSigningKeys;
1090 }
1091 }
1092
Todd Kennedy66c55532016-02-26 16:22:11 -08001093 private static void collectCertificatesInternal(Package pkg, int parseFlags)
1094 throws PackageParserException {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001095 pkg.mCertificates = null;
1096 pkg.mSignatures = null;
1097 pkg.mSigningKeys = null;
1098
Todd Kennedy3398be82015-12-02 13:40:49 -08001099 collectCertificates(pkg, new File(pkg.baseCodePath), pkg.applicationInfo.flags, parseFlags);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001100
1101 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
Todd Kennedy3398be82015-12-02 13:40:49 -08001102 for (int i = 0; i < pkg.splitCodePaths.length; i++) {
1103 collectCertificates(pkg, new File(pkg.splitCodePaths[i]), pkg.splitFlags[i],
1104 parseFlags);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001105 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001106 }
1107 }
1108
Todd Kennedy3398be82015-12-02 13:40:49 -08001109 private static void collectCertificates(Package pkg, File apkFile, int apkFlags, int parseFlags)
Jeff Sharkey275e0852014-06-17 18:18:49 -07001110 throws PackageParserException {
Todd Kennedy3398be82015-12-02 13:40:49 -08001111 final boolean hasCode = (apkFlags & ApplicationInfo.FLAG_HAS_CODE) != 0;
1112 final boolean requireCode = ((parseFlags & PARSE_ENFORCE_CODE) != 0) && hasCode;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001113 final String apkPath = apkFile.getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001114
Alex Klyubine4157182016-01-05 13:27:05 -08001115 // Try to verify the APK using APK Signature Scheme v2.
1116 boolean verified = false;
1117 {
1118 Certificate[][] allSignersCerts = null;
1119 Signature[] signatures = null;
1120 try {
1121 allSignersCerts = ApkSignatureSchemeV2Verifier.verify(apkPath);
1122 signatures = convertToSignatures(allSignersCerts);
1123 // APK verified using APK Signature Scheme v2.
1124 verified = true;
1125 } catch (ApkSignatureSchemeV2Verifier.SignatureNotFoundException e) {
1126 // No APK Signature Scheme v2 signature found
1127 } catch (Exception e) {
1128 // APK Signature Scheme v2 signature was found but did not verify
1129 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1130 "Failed to collect certificates from " + apkPath
1131 + " using APK Signature Scheme v2",
1132 e);
1133 }
1134
1135 if (verified) {
1136 if (pkg.mCertificates == null) {
1137 pkg.mCertificates = allSignersCerts;
1138 pkg.mSignatures = signatures;
1139 pkg.mSigningKeys = new ArraySet<>(allSignersCerts.length);
1140 for (int i = 0; i < allSignersCerts.length; i++) {
1141 Certificate[] signerCerts = allSignersCerts[i];
1142 Certificate signerCert = signerCerts[0];
1143 pkg.mSigningKeys.add(signerCert.getPublicKey());
1144 }
1145 } else {
1146 if (!Signature.areExactMatch(pkg.mSignatures, signatures)) {
1147 throw new PackageParserException(
1148 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
1149 apkPath + " has mismatched certificates");
1150 }
1151 }
1152 // Not yet done, because we need to confirm that AndroidManifest.xml exists and,
1153 // if requested, that classes.dex exists.
1154 }
1155 }
1156
Todd Kennedy373f0b42015-12-16 14:45:14 -08001157 boolean codeFound = false;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001158 StrictJarFile jarFile = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 try {
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001160 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor");
Alex Klyubin9b59bc42016-03-24 12:02:20 -07001161 // Ignore signature stripping protections when verifying APKs from system partition.
1162 // For those APKs we only care about extracting signer certificates, and don't care
1163 // about verifying integrity.
1164 boolean signatureSchemeRollbackProtectionsEnforced =
1165 (parseFlags & PARSE_IS_SYSTEM) == 0;
Alex Klyubine4157182016-01-05 13:27:05 -08001166 jarFile = new StrictJarFile(
1167 apkPath,
Alex Klyubin9b59bc42016-03-24 12:02:20 -07001168 !verified, // whether to verify JAR signature
1169 signatureSchemeRollbackProtectionsEnforced);
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001170 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001171
Jeff Sharkey275e0852014-06-17 18:18:49 -07001172 // Always verify manifest, regardless of source
1173 final ZipEntry manifestEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
1174 if (manifestEntry == null) {
1175 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1176 "Package " + apkPath + " has no manifest");
1177 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001178
Alex Klyubine4157182016-01-05 13:27:05 -08001179 // Optimization: early termination when APK already verified
1180 if (verified) {
1181 if ((requireCode) && (jarFile.findEntry(BYTECODE_FILENAME) == null)) {
1182 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1183 "Package " + apkPath + " code is missing");
1184 }
1185 return;
1186 }
1187
1188 // APK's integrity needs to be verified using JAR signature scheme.
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001189 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "buildVerifyList");
Jeff Sharkey275e0852014-06-17 18:18:49 -07001190 final List<ZipEntry> toVerify = new ArrayList<>();
1191 toVerify.add(manifestEntry);
1192
1193 // If we're parsing an untrusted package, verify all contents
Todd Kennedy373f0b42015-12-16 14:45:14 -08001194 if ((parseFlags & PARSE_IS_SYSTEM) == 0) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001195 final Iterator<ZipEntry> i = jarFile.iterator();
1196 while (i.hasNext()) {
1197 final ZipEntry entry = i.next();
1198
1199 if (entry.isDirectory()) continue;
Christopher Tatef3d939c2015-09-17 12:25:51 -07001200
1201 final String entryName = entry.getName();
1202 if (entryName.startsWith("META-INF/")) continue;
1203 if (entryName.equals(ANDROID_MANIFEST_FILENAME)) continue;
1204 if (entryName.equals(BYTECODE_FILENAME)) {
1205 codeFound = true;
1206 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001207
1208 toVerify.add(entry);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001209 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001210 }
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001211 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001212
Christopher Tatef3d939c2015-09-17 12:25:51 -07001213 if (!codeFound && requireCode) {
1214 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1215 "Package " + apkPath + " code is missing");
1216 }
1217
Jeff Sharkey275e0852014-06-17 18:18:49 -07001218 // Verify that entries are signed consistently with the first entry
1219 // we encountered. Note that for splits, certificates may have
1220 // already been populated during an earlier parse of a base APK.
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001221 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyEntries");
Jeff Sharkey275e0852014-06-17 18:18:49 -07001222 for (ZipEntry entry : toVerify) {
1223 final Certificate[][] entryCerts = loadCertificates(jarFile, entry);
1224 if (ArrayUtils.isEmpty(entryCerts)) {
1225 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1226 "Package " + apkPath + " has no certificates at entry "
1227 + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001228 }
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001229 final Signature[] entrySignatures = convertToSignatures(entryCerts);
Kenny Rootd2d29252011-08-08 11:27:57 -07001230
Jeff Sharkey275e0852014-06-17 18:18:49 -07001231 if (pkg.mCertificates == null) {
1232 pkg.mCertificates = entryCerts;
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001233 pkg.mSignatures = entrySignatures;
dcashman55b10782014-04-09 14:20:38 -07001234 pkg.mSigningKeys = new ArraySet<PublicKey>();
1235 for (int i=0; i < entryCerts.length; i++) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001236 pkg.mSigningKeys.add(entryCerts[i][0].getPublicKey());
Kenny Rootbcc954d2011-08-08 16:19:08 -07001237 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001238 } else {
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001239 if (!Signature.areExactMatch(pkg.mSignatures, entrySignatures)) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001240 throw new PackageParserException(
1241 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, "Package " + apkPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001242 + " has mismatched certificates at entry "
Jeff Sharkey275e0852014-06-17 18:18:49 -07001243 + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001244 }
1245 }
1246 }
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001247 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeybc097552014-09-09 14:57:26 -07001248 } catch (GeneralSecurityException e) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001249 throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING,
1250 "Failed to collect certificates from " + apkPath, e);
Jeff Sharkeybc097552014-09-09 14:57:26 -07001251 } catch (IOException | RuntimeException e) {
1252 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1253 "Failed to collect certificates from " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001254 } finally {
1255 closeQuietly(jarFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001256 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001257 }
1258
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001259 private static Signature[] convertToSignatures(Certificate[][] certs)
1260 throws CertificateEncodingException {
1261 final Signature[] res = new Signature[certs.length];
1262 for (int i = 0; i < certs.length; i++) {
1263 res[i] = new Signature(certs[i]);
1264 }
1265 return res;
1266 }
1267
Jeff Sharkey275e0852014-06-17 18:18:49 -07001268 /**
1269 * Utility method that retrieves lightweight details about a single APK
1270 * file, including package name, split name, and install location.
1271 *
1272 * @param apkFile path to a single APK
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001273 * @param flags optional parse flags, such as
1274 * {@link #PARSE_COLLECT_CERTIFICATES}
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001275 */
Jeff Sharkey275e0852014-06-17 18:18:49 -07001276 public static ApkLite parseApkLite(File apkFile, int flags)
1277 throws PackageParserException {
1278 final String apkPath = apkFile.getAbsolutePath();
1279
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001280 AssetManager assets = null;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001281 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001282 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001283 assets = new AssetManager();
1284 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 -08001285 Build.VERSION.RESOURCES_SDK_INT);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001286
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001287 int cookie = assets.addAssetPath(apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001288 if (cookie == 0) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001289 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1290 "Failed to parse " + apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001291 }
1292
Kenny Root05ca4c92011-09-15 10:36:25 -07001293 final DisplayMetrics metrics = new DisplayMetrics();
1294 metrics.setToDefaults();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001295
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001296 final Resources res = new Resources(assets, metrics, null);
1297 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Kenny Root05ca4c92011-09-15 10:36:25 -07001298
Jeff Sharkey275e0852014-06-17 18:18:49 -07001299 final Signature[] signatures;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001300 if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
1301 // TODO: factor signature related items out of Package object
1302 final Package tempPkg = new Package(null);
Todd Kennedy373f0b42015-12-16 14:45:14 -08001303 collectCertificates(tempPkg, apkFile, 0 /*apkFlags*/, 0 /*flags*/);
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001304 signatures = tempPkg.mSignatures;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001305 } else {
1306 signatures = null;
1307 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001308
Jeff Sharkey275e0852014-06-17 18:18:49 -07001309 final AttributeSet attrs = parser;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -07001310 return parseApkLite(apkPath, res, parser, attrs, flags, signatures);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001311
1312 } catch (XmlPullParserException | IOException | RuntimeException e) {
1313 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1314 "Failed to parse " + apkPath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001315 } finally {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001316 IoUtils.closeQuietly(parser);
1317 IoUtils.closeQuietly(assets);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001318 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319 }
1320
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001321 private static String validateName(String name, boolean requireSeparator,
1322 boolean requireFilename) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001323 final int N = name.length();
1324 boolean hasSep = false;
1325 boolean front = true;
1326 for (int i=0; i<N; i++) {
1327 final char c = name.charAt(i);
1328 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1329 front = false;
1330 continue;
1331 }
1332 if (!front) {
1333 if ((c >= '0' && c <= '9') || c == '_') {
1334 continue;
1335 }
1336 }
1337 if (c == '.') {
1338 hasSep = true;
1339 front = true;
1340 continue;
1341 }
1342 return "bad character '" + c + "'";
1343 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001344 if (requireFilename && !FileUtils.isValidExtFilename(name)) {
1345 return "Invalid filename";
1346 }
1347 return hasSep || !requireSeparator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348 ? null : "must have at least one '.' separator";
1349 }
1350
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001351 private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
Svet Ganov354cd3c2015-12-17 11:35:04 -08001352 AttributeSet attrs) throws IOException, XmlPullParserException,
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001353 PackageParserException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001354
1355 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001356 while ((type = parser.next()) != XmlPullParser.START_TAG
1357 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 }
1359
Kenny Rootd2d29252011-08-08 11:27:57 -07001360 if (type != XmlPullParser.START_TAG) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001361 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1362 "No start tag found");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001364 if (!parser.getName().equals(TAG_MANIFEST)) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001365 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1366 "No <manifest> tag");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001367 }
1368
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001369 final String packageName = attrs.getAttributeValue(null, "package");
1370 if (!"android".equals(packageName)) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001371 final String error = validateName(packageName, true, true);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001372 if (error != null) {
1373 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1374 "Invalid manifest package: " + error);
1375 }
1376 }
1377
Jeff Sharkey275e0852014-06-17 18:18:49 -07001378 String splitName = attrs.getAttributeValue(null, "split");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001379 if (splitName != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001380 if (splitName.length() == 0) {
1381 splitName = null;
1382 } else {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001383 final String error = validateName(splitName, false, false);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001384 if (error != null) {
1385 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1386 "Invalid manifest split: " + error);
1387 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001388 }
1389 }
1390
1391 return Pair.create(packageName.intern(),
1392 (splitName != null) ? splitName.intern() : splitName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 }
1394
Jeff Sharkeybe520fb2014-07-04 18:23:17 -07001395 private static ApkLite parseApkLite(String codePath, Resources res, XmlPullParser parser,
Jeff Sharkey275e0852014-06-17 18:18:49 -07001396 AttributeSet attrs, int flags, Signature[] signatures) throws IOException,
1397 XmlPullParserException, PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001398 final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001399
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001400 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001401 int versionCode = 0;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001402 int revisionCode = 0;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001403 boolean coreApp = false;
Narayan Kamathff110bd2014-07-04 18:30:45 +01001404 boolean multiArch = false;
Selim Gurun2d291d82016-02-05 17:50:53 -08001405 boolean use32bitAbi = false;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001406 boolean extractNativeLibs = true;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001407
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001408 for (int i = 0; i < attrs.getAttributeCount(); i++) {
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001409 final String attr = attrs.getAttributeName(i);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001410 if (attr.equals("installLocation")) {
1411 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001412 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001413 } else if (attr.equals("versionCode")) {
1414 versionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001415 } else if (attr.equals("revisionCode")) {
1416 revisionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001417 } else if (attr.equals("coreApp")) {
1418 coreApp = attrs.getAttributeBooleanValue(i, false);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001419 }
1420 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001421
1422 // Only search the tree when the tag is directly below <manifest>
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001423 int type;
Kenny Root05ca4c92011-09-15 10:36:25 -07001424 final int searchDepth = parser.getDepth() + 1;
1425
1426 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
1427 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1428 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
1429 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1430 continue;
1431 }
1432
1433 if (parser.getDepth() == searchDepth && "package-verifier".equals(parser.getName())) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001434 final VerifierInfo verifier = parseVerifier(res, parser, attrs, flags);
Kenny Root05ca4c92011-09-15 10:36:25 -07001435 if (verifier != null) {
1436 verifiers.add(verifier);
1437 }
1438 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001439
1440 if (parser.getDepth() == searchDepth && "application".equals(parser.getName())) {
1441 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1442 final String attr = attrs.getAttributeName(i);
1443 if ("multiArch".equals(attr)) {
1444 multiArch = attrs.getAttributeBooleanValue(i, false);
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001445 }
Selim Gurun2d291d82016-02-05 17:50:53 -08001446 if ("use32bitAbi".equals(attr)) {
1447 use32bitAbi = attrs.getAttributeBooleanValue(i, false);
Tao Baic9a02372016-01-12 15:02:24 -08001448 }
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001449 if ("extractNativeLibs".equals(attr)) {
1450 extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
Narayan Kamatha8755a82014-07-15 12:26:35 +01001451 }
1452 }
1453 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001454 }
1455
Jeff Sharkeybe520fb2014-07-04 18:23:17 -07001456 return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode,
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001457 revisionCode, installLocation, verifiers, signatures, coreApp, multiArch,
Selim Gurun2d291d82016-02-05 17:50:53 -08001458 use32bitAbi, extractNativeLibs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001459 }
1460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 /**
1462 * Temporary.
1463 */
1464 static public Signature stringToSignature(String str) {
1465 final int N = str.length();
1466 byte[] sig = new byte[N];
1467 for (int i=0; i<N; i++) {
1468 sig[i] = (byte)str.charAt(i);
1469 }
1470 return new Signature(sig);
1471 }
1472
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001473 /**
Svet Ganov354cd3c2015-12-17 11:35:04 -08001474 * Parses a child package and adds it to the parent if successful. If you add
1475 * new tags that need to be supported by child packages make sure to add them
1476 * to {@link #CHILD_PACKAGE_TAGS}.
1477 *
1478 * @param parentPkg The parent that contains the child
1479 * @param res Resources against which to resolve values
1480 * @param parser Parser of the manifest
1481 * @param flags Flags about how to parse
1482 * @param outError Human readable error if parsing fails
1483 * @return True of parsing succeeded.
1484 *
1485 * @throws XmlPullParserException
1486 * @throws IOException
1487 */
1488 private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser,
1489 int flags, String[] outError) throws XmlPullParserException, IOException {
1490 // Let ppl not abuse this mechanism by limiting the packages per APK
1491 if (parentPkg.childPackages != null && parentPkg.childPackages.size() + 2
1492 > MAX_PACKAGES_PER_APK) {
1493 outError[0] = "Maximum number of packages per APK is: " + MAX_PACKAGES_PER_APK;
1494 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1495 return false;
1496 }
1497
1498 // Make sure we have a valid child package name
1499 String childPackageName = parser.getAttributeValue(null, "package");
1500 if (validateName(childPackageName, true, false) != null) {
1501 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1502 return false;
1503 }
1504
1505 // Child packages must be unique
1506 if (childPackageName.equals(parentPkg.packageName)) {
1507 String message = "Child package name cannot be equal to parent package name: "
1508 + parentPkg.packageName;
1509 Slog.w(TAG, message);
1510 outError[0] = message;
1511 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1512 return false;
1513 }
1514
1515 // Child packages must be unique
1516 if (parentPkg.hasChildPackage(childPackageName)) {
1517 String message = "Duplicate child package:" + childPackageName;
1518 Slog.w(TAG, message);
1519 outError[0] = message;
1520 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1521 return false;
1522 }
1523
1524 // Go ahead and parse the child
1525 Package childPkg = new Package(childPackageName);
1526
1527 // Child package inherits parent version code/name/target SDK
1528 childPkg.mVersionCode = parentPkg.mVersionCode;
1529 childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
1530 childPkg.mVersionName = parentPkg.mVersionName;
1531 childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
Todd Kennedy89d60182016-03-11 11:18:32 -08001532 childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001533
1534 childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
1535 if (childPkg == null) {
1536 // If we got null then error was set during child parsing
1537 return false;
1538 }
1539
1540 // Set the parent-child relation
1541 if (parentPkg.childPackages == null) {
1542 parentPkg.childPackages = new ArrayList<>();
1543 }
1544 parentPkg.childPackages.add(childPkg);
1545 childPkg.parentPackage = parentPkg;
1546
1547 return true;
1548 }
1549
1550 /**
1551 * Parse the manifest of a <em>base APK</em>. When adding new features you
1552 * need to consider whether they should be supported by split APKs and child
1553 * packages.
1554 *
1555 * @param res The resources from which to resolve values
1556 * @param parser The manifest parser
1557 * @param flags Flags how to parse
1558 * @param outError Human readable error message
1559 * @return Parsed package or null on error.
1560 *
1561 * @throws XmlPullParserException
1562 * @throws IOException
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001563 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001564 private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001565 String[] outError) throws XmlPullParserException, IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001566 final String splitName;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001567 final String pkgName;
1568
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001569 try {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001570 Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001571 pkgName = packageSplit.first;
1572 splitName = packageSplit.second;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001573
1574 if (!TextUtils.isEmpty(splitName)) {
1575 outError[0] = "Expected base APK, but found split " + splitName;
1576 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1577 return null;
1578 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001579 } catch (PackageParserException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1581 return null;
1582 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001583
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001584 final Package pkg = new Package(pkgName);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001585
Svet Ganov354cd3c2015-12-17 11:35:04 -08001586 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 com.android.internal.R.styleable.AndroidManifest);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001588
Dianne Hackborn8472e612014-01-23 17:57:20 -08001589 pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001590 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001591 pkg.baseRevisionCode = sa.getInteger(
1592 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001593 pkg.mVersionName = sa.getNonConfigurationString(
1594 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 if (pkg.mVersionName != null) {
1596 pkg.mVersionName = pkg.mVersionName.intern();
1597 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001598
1599 pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
1600
1601 sa.recycle();
1602
1603 return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
1604 }
1605
1606 /**
1607 * This is the common parsing routing for handling parent and child
1608 * packages in a base APK. The difference between parent and child
1609 * parsing is that some targs are not supported by child packages as
1610 * well as some manifest attributes are ignored. The implementation
1611 * assumes the calling code already handled the manifest tag if needed
1612 * (this applies to the parent only).
1613 *
1614 * @param pkg The package which to populate
1615 * @param acceptedTags Which tags to handle, null to handle all
1616 * @param res Resources against which to resolve values
1617 * @param parser Parser of the manifest
1618 * @param flags Flags about how to parse
1619 * @param outError Human readable error if parsing fails
1620 * @return The package if parsing succeeded or null.
1621 *
1622 * @throws XmlPullParserException
1623 * @throws IOException
1624 */
1625 private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
1626 XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
1627 IOException {
1628 final boolean trustedOverlay = (flags & PARSE_TRUSTED_OVERLAY) != 0;
1629 mParseInstrumentationArgs = null;
1630 mParseActivityArgs = null;
1631 mParseServiceArgs = null;
1632 mParseProviderArgs = null;
1633
1634 int type;
1635 boolean foundApp = false;
1636
1637 TypedArray sa = res.obtainAttributes(parser,
1638 com.android.internal.R.styleable.AndroidManifest);
1639
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001640 String str = sa.getNonConfigurationString(
1641 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
1642 if (str != null && str.length() > 0) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001643 String nameError = validateName(str, true, false);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001644 if (nameError != null && !"android".equals(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 outError[0] = "<manifest> specifies bad sharedUserId name \""
1646 + str + "\": " + nameError;
1647 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
1648 return null;
1649 }
1650 pkg.mSharedUserId = str.intern();
1651 pkg.mSharedUserLabel = sa.getResourceId(
1652 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
1653 }
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -08001654
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08001655 pkg.installLocation = sa.getInteger(
1656 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001657 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -07001658 pkg.applicationInfo.installLocation = pkg.installLocation;
Kenny Root7cb9be22012-05-30 15:30:37 -07001659
Alan Viverettefd274a02014-03-27 15:39:15 -07001660
Kenny Root7cb9be22012-05-30 15:30:37 -07001661 /* Set the global "forward lock" flag */
1662 if ((flags & PARSE_FORWARD_LOCK) != 0) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08001663 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
Kenny Root7cb9be22012-05-30 15:30:37 -07001664 }
1665
1666 /* Set the global "on SD card" flag */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001667 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
Kenny Root7cb9be22012-05-30 15:30:37 -07001668 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
1669 }
1670
Svet Ganov2acf0632015-11-24 19:10:59 -08001671 if ((flags & PARSE_IS_EPHEMERAL) != 0) {
1672 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_EPHEMERAL;
1673 }
1674
Dianne Hackborn723738c2009-06-25 19:48:04 -07001675 // Resource boolean are -1, so 1 means we don't know the value.
1676 int supportsSmallScreens = 1;
1677 int supportsNormalScreens = 1;
1678 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001679 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001680 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001681 int anyDensity = 1;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -07001684 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1685 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1686 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 continue;
1688 }
1689
1690 String tagName = parser.getName();
Svet Ganov354cd3c2015-12-17 11:35:04 -08001691
1692 if (acceptedTags != null && !acceptedTags.contains(tagName)) {
1693 Slog.w(TAG, "Skipping unsupported element under <manifest>: "
1694 + tagName + " at " + mArchiveSourcePath + " "
1695 + parser.getPositionDescription());
1696 XmlUtils.skipCurrentTag(parser);
1697 continue;
1698 }
1699
1700 if (tagName.equals(TAG_APPLICATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 if (foundApp) {
1702 if (RIGID_PARSER) {
1703 outError[0] = "<manifest> has more than one <application>";
1704 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1705 return null;
1706 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07001707 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 XmlUtils.skipCurrentTag(parser);
1709 continue;
1710 }
1711 }
1712
1713 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001714 if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001715 return null;
1716 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001717 } else if (tagName.equals(TAG_OVERLAY)) {
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01001718 pkg.mTrustedOverlay = trustedOverlay;
1719
Svet Ganov354cd3c2015-12-17 11:35:04 -08001720 sa = res.obtainAttributes(parser,
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01001721 com.android.internal.R.styleable.AndroidManifestResourceOverlay);
1722 pkg.mOverlayTarget = sa.getString(
1723 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
1724 pkg.mOverlayPriority = sa.getInt(
1725 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
1726 -1);
1727 sa.recycle();
1728
1729 if (pkg.mOverlayTarget == null) {
1730 outError[0] = "<overlay> does not specify a target package";
1731 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1732 return null;
1733 }
1734 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
1735 outError[0] = "<overlay> priority must be between 0 and 9999";
1736 mParseError =
1737 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1738 return null;
1739 }
1740 XmlUtils.skipCurrentTag(parser);
1741
Svet Ganov354cd3c2015-12-17 11:35:04 -08001742 } else if (tagName.equals(TAG_KEY_SETS)) {
1743 if (!parseKeySets(pkg, res, parser, outError)) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08001744 return null;
1745 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001746 } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
1747 if (parsePermissionGroup(pkg, flags, res, parser, outError) == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001748 return null;
1749 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001750 } else if (tagName.equals(TAG_PERMISSION)) {
1751 if (parsePermission(pkg, res, parser, outError) == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001752 return null;
1753 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001754 } else if (tagName.equals(TAG_PERMISSION_TREE)) {
1755 if (parsePermissionTree(pkg, res, parser, outError) == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756 return null;
1757 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001758 } else if (tagName.equals(TAG_USES_PERMISSION)) {
1759 if (!parseUsesPermission(pkg, res, parser)) {
Svetoslav96a77162015-04-03 13:58:33 -07001760 return null;
1761 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001762 } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
1763 || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
1764 if (!parseUsesPermission(pkg, res, parser)) {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07001765 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001766 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001767 } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 ConfigurationInfo cPref = new ConfigurationInfo();
Svet Ganov354cd3c2015-12-17 11:35:04 -08001769 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
1771 cPref.reqTouchScreen = sa.getInt(
1772 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
1773 Configuration.TOUCHSCREEN_UNDEFINED);
1774 cPref.reqKeyboardType = sa.getInt(
1775 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
1776 Configuration.KEYBOARD_UNDEFINED);
1777 if (sa.getBoolean(
1778 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
1779 false)) {
1780 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
1781 }
1782 cPref.reqNavigation = sa.getInt(
1783 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
1784 Configuration.NAVIGATION_UNDEFINED);
1785 if (sa.getBoolean(
1786 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
1787 false)) {
1788 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
1789 }
1790 sa.recycle();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001791 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792
1793 XmlUtils.skipCurrentTag(parser);
1794
Svet Ganov354cd3c2015-12-17 11:35:04 -08001795 } else if (tagName.equals(TAG_USES_FEATURE)) {
1796 FeatureInfo fi = parseUsesFeature(res, parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001797 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
1798
Dianne Hackborn49237342009-08-27 20:08:01 -07001799 if (fi.name == null) {
1800 ConfigurationInfo cPref = new ConfigurationInfo();
1801 cPref.reqGlEsVersion = fi.reqGlEsVersion;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001802 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
Dianne Hackborn49237342009-08-27 20:08:01 -07001803 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07001804
1805 XmlUtils.skipCurrentTag(parser);
1806
Svet Ganov354cd3c2015-12-17 11:35:04 -08001807 } else if (tagName.equals(TAG_FEATURE_GROUP)) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07001808 FeatureGroupInfo group = new FeatureGroupInfo();
1809 ArrayList<FeatureInfo> features = null;
1810 final int innerDepth = parser.getDepth();
1811 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1812 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
1813 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1814 continue;
1815 }
Adam Lesinski2c72b682014-06-24 09:56:01 -07001816
Adam Lesinskid3edfde2014-08-08 17:32:44 -07001817 final String innerTagName = parser.getName();
1818 if (innerTagName.equals("uses-feature")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001819 FeatureInfo featureInfo = parseUsesFeature(res, parser);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07001820 // FeatureGroups are stricter and mandate that
1821 // any <uses-feature> declared are mandatory.
1822 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
1823 features = ArrayUtils.add(features, featureInfo);
1824 } else {
1825 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
1826 " at " + mArchiveSourcePath + " " +
1827 parser.getPositionDescription());
1828 }
1829 XmlUtils.skipCurrentTag(parser);
1830 }
1831
1832 if (features != null) {
1833 group.features = new FeatureInfo[features.size()];
1834 group.features = features.toArray(group.features);
1835 }
1836 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
Adam Lesinski2c72b682014-06-24 09:56:01 -07001837
Svet Ganov354cd3c2015-12-17 11:35:04 -08001838 } else if (tagName.equals(TAG_USES_SDK)) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001839 if (SDK_VERSION > 0) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001840 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001841 com.android.internal.R.styleable.AndroidManifestUsesSdk);
1842
Dianne Hackborn851a5412009-05-08 12:06:44 -07001843 int minVers = 0;
1844 String minCode = null;
1845 int targetVers = 0;
1846 String targetCode = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001847
Dianne Hackborn851a5412009-05-08 12:06:44 -07001848 TypedValue val = sa.peekValue(
1849 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
1850 if (val != null) {
1851 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
1852 targetCode = minCode = val.string.toString();
1853 } else {
1854 // If it's not a string, it's an integer.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001855 targetVers = minVers = val.data;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001856 }
1857 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001858
Dianne Hackborn851a5412009-05-08 12:06:44 -07001859 val = sa.peekValue(
1860 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
1861 if (val != null) {
1862 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
Todd Kennedy89d60182016-03-11 11:18:32 -08001863 targetCode = val.string.toString();
1864 if (minCode == null) {
1865 minCode = targetCode;
1866 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07001867 } else {
1868 // If it's not a string, it's an integer.
1869 targetVers = val.data;
Todd Kennedy89d60182016-03-11 11:18:32 -08001870 if (minVers == 0) {
1871 minVers = targetVers;
1872 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07001873 }
1874 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001876 sa.recycle();
1877
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001878 if (minCode != null) {
Dianne Hackbornffcda102014-04-24 13:06:27 -07001879 boolean allowedCodename = false;
1880 for (String codename : SDK_CODENAMES) {
1881 if (minCode.equals(codename)) {
1882 allowedCodename = true;
1883 break;
1884 }
1885 }
1886 if (!allowedCodename) {
1887 if (SDK_CODENAMES.length > 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001888 outError[0] = "Requires development platform " + minCode
Dianne Hackbornffcda102014-04-24 13:06:27 -07001889 + " (current platform is any of "
1890 + Arrays.toString(SDK_CODENAMES) + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001891 } else {
1892 outError[0] = "Requires development platform " + minCode
1893 + " but this is a release platform.";
1894 }
1895 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1896 return null;
1897 }
Todd Kennedy89d60182016-03-11 11:18:32 -08001898 pkg.applicationInfo.minSdkVersion = minCode;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001899 } else if (minVers > SDK_VERSION) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001900 outError[0] = "Requires newer sdk version #" + minVers
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001901 + " (current version is #" + SDK_VERSION + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001902 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1903 return null;
Todd Kennedy89d60182016-03-11 11:18:32 -08001904 } else {
1905 pkg.applicationInfo.minSdkVersion = Integer.toString(minVers);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001906 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001907
Dianne Hackborn851a5412009-05-08 12:06:44 -07001908 if (targetCode != null) {
Dianne Hackbornffcda102014-04-24 13:06:27 -07001909 boolean allowedCodename = false;
1910 for (String codename : SDK_CODENAMES) {
1911 if (targetCode.equals(codename)) {
1912 allowedCodename = true;
1913 break;
1914 }
1915 }
1916 if (!allowedCodename) {
1917 if (SDK_CODENAMES.length > 0) {
Dianne Hackborn851a5412009-05-08 12:06:44 -07001918 outError[0] = "Requires development platform " + targetCode
Dianne Hackbornffcda102014-04-24 13:06:27 -07001919 + " (current platform is any of "
1920 + Arrays.toString(SDK_CODENAMES) + ")";
Dianne Hackborn851a5412009-05-08 12:06:44 -07001921 } else {
1922 outError[0] = "Requires development platform " + targetCode
1923 + " but this is a release platform.";
1924 }
1925 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1926 return null;
1927 }
1928 // If the code matches, it definitely targets this SDK.
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001929 pkg.applicationInfo.targetSdkVersion
1930 = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
1931 } else {
1932 pkg.applicationInfo.targetSdkVersion = targetVers;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001933 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001934 }
1935
1936 XmlUtils.skipCurrentTag(parser);
1937
Svet Ganov354cd3c2015-12-17 11:35:04 -08001938 } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
1939 sa = res.obtainAttributes(parser,
Dianne Hackborn723738c2009-06-25 19:48:04 -07001940 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
1941
Dianne Hackborndf6e9802011-05-26 14:20:23 -07001942 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
1943 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
1944 0);
1945 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
1946 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
1947 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07001948 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
1949 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
1950 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07001951
Dianne Hackborn723738c2009-06-25 19:48:04 -07001952 // This is a trick to get a boolean and still able to detect
1953 // if a value was actually set.
1954 supportsSmallScreens = sa.getInteger(
1955 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
1956 supportsSmallScreens);
1957 supportsNormalScreens = sa.getInteger(
1958 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
1959 supportsNormalScreens);
1960 supportsLargeScreens = sa.getInteger(
1961 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
1962 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001963 supportsXLargeScreens = sa.getInteger(
1964 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
1965 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001966 resizeable = sa.getInteger(
1967 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001968 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001969 anyDensity = sa.getInteger(
1970 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
1971 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07001972
1973 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001974
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07001975 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001976
Svet Ganov354cd3c2015-12-17 11:35:04 -08001977 } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
1978 sa = res.obtainAttributes(parser,
Dianne Hackborn854060af2009-07-09 18:14:31 -07001979 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
1980
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001981 // Note: don't allow this value to be a reference to a resource
1982 // that may change.
Dianne Hackborn854060af2009-07-09 18:14:31 -07001983 String name = sa.getNonResourceString(
1984 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
1985
1986 sa.recycle();
1987
1988 if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
1989 if (pkg.protectedBroadcasts == null) {
1990 pkg.protectedBroadcasts = new ArrayList<String>();
1991 }
1992 if (!pkg.protectedBroadcasts.contains(name)) {
1993 pkg.protectedBroadcasts.add(name.intern());
1994 }
1995 }
1996
1997 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001998
Svet Ganov354cd3c2015-12-17 11:35:04 -08001999 } else if (tagName.equals(TAG_INSTRUMENTATION)) {
2000 if (parseInstrumentation(pkg, res, parser, outError) == null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002001 return null;
2002 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002003 } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
2004 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002005 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2006
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002007 String orig =sa.getNonConfigurationString(
2008 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002009 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002010 if (pkg.mOriginalPackages == null) {
2011 pkg.mOriginalPackages = new ArrayList<String>();
2012 pkg.mRealPackage = pkg.packageName;
2013 }
2014 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002015 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002016
2017 sa.recycle();
2018
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002019 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002020
Svet Ganov354cd3c2015-12-17 11:35:04 -08002021 } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
2022 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002023 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2024
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002025 String name = sa.getNonConfigurationString(
2026 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002027
2028 sa.recycle();
2029
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002030 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002031 if (pkg.mAdoptPermissions == null) {
2032 pkg.mAdoptPermissions = new ArrayList<String>();
2033 }
2034 pkg.mAdoptPermissions.add(name);
2035 }
2036
2037 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002038
Svet Ganov354cd3c2015-12-17 11:35:04 -08002039 } else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002040 // Just skip this tag
2041 XmlUtils.skipCurrentTag(parser);
2042 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002043
Svet Ganov354cd3c2015-12-17 11:35:04 -08002044 } else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002045 // Just skip this tag
2046 XmlUtils.skipCurrentTag(parser);
2047 continue;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002048 } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
Michael Wrighteaeb1902013-09-05 18:15:57 -07002049 XmlUtils.skipCurrentTag(parser);
2050 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002051
Svet Ganov354cd3c2015-12-17 11:35:04 -08002052 } else if (tagName.equals(TAG_EAT_COMMENT)) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002053 // Just skip this tag
2054 XmlUtils.skipCurrentTag(parser);
2055 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002056
Svet Ganov354cd3c2015-12-17 11:35:04 -08002057 } else if (tagName.equals(TAG_PACKAGE)) {
2058 if (!parseBaseApkChild(pkg, res, parser, flags, outError)) {
2059 // If parsing a child failed the error is already set
2060 return null;
2061 }
Dianne Hackborn854060af2009-07-09 18:14:31 -07002062 } else if (RIGID_PARSER) {
2063 outError[0] = "Bad element under <manifest>: "
2064 + parser.getName();
2065 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2066 return null;
2067
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002068 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002069 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002070 + " at " + mArchiveSourcePath + " "
2071 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002072 XmlUtils.skipCurrentTag(parser);
2073 continue;
2074 }
2075 }
2076
2077 if (!foundApp && pkg.instrumentation.size() == 0) {
2078 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
2079 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
2080 }
2081
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002082 final int NP = PackageParser.NEW_PERMISSIONS.length;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002083 StringBuilder implicitPerms = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002084 for (int ip=0; ip<NP; ip++) {
2085 final PackageParser.NewPermissionInfo npi
2086 = PackageParser.NEW_PERMISSIONS[ip];
2087 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
2088 break;
2089 }
2090 if (!pkg.requestedPermissions.contains(npi.name)) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002091 if (implicitPerms == null) {
2092 implicitPerms = new StringBuilder(128);
2093 implicitPerms.append(pkg.packageName);
2094 implicitPerms.append(": compat added ");
2095 } else {
2096 implicitPerms.append(' ');
2097 }
2098 implicitPerms.append(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002099 pkg.requestedPermissions.add(npi.name);
2100 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002101 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002102 if (implicitPerms != null) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002103 Slog.i(TAG, implicitPerms.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002104 }
Dianne Hackborn79245122012-03-12 10:51:26 -07002105
2106 final int NS = PackageParser.SPLIT_PERMISSIONS.length;
2107 for (int is=0; is<NS; is++) {
2108 final PackageParser.SplitPermissionInfo spi
2109 = PackageParser.SPLIT_PERMISSIONS[is];
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -07002110 if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
2111 || !pkg.requestedPermissions.contains(spi.rootPerm)) {
Dianne Hackborn5e4705a2012-04-06 12:55:53 -07002112 continue;
Dianne Hackborn79245122012-03-12 10:51:26 -07002113 }
2114 for (int in=0; in<spi.newPerms.length; in++) {
2115 final String perm = spi.newPerms[in];
2116 if (!pkg.requestedPermissions.contains(perm)) {
2117 pkg.requestedPermissions.add(perm);
Dianne Hackborn79245122012-03-12 10:51:26 -07002118 }
2119 }
2120 }
2121
Dianne Hackborn723738c2009-06-25 19:48:04 -07002122 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
2123 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002124 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002125 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
2126 }
2127 if (supportsNormalScreens != 0) {
2128 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
2129 }
2130 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
2131 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002132 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002133 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
2134 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002135 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
2136 && pkg.applicationInfo.targetSdkVersion
2137 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
2138 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
2139 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002140 if (resizeable < 0 || (resizeable > 0
2141 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002142 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002143 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
2144 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002145 if (anyDensity < 0 || (anyDensity > 0
2146 && pkg.applicationInfo.targetSdkVersion
2147 >= android.os.Build.VERSION_CODES.DONUT)) {
2148 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07002149 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07002150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002151 return pkg;
2152 }
2153
Todd Kennedy27c24fb2015-09-17 16:49:25 -07002154 private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002155 FeatureInfo fi = new FeatureInfo();
2156 TypedArray sa = res.obtainAttributes(attrs,
2157 com.android.internal.R.styleable.AndroidManifestUsesFeature);
2158 // Note: don't allow this value to be a reference to a resource
2159 // that may change.
2160 fi.name = sa.getNonResourceString(
2161 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
Jeff Sharkey115d2c12016-02-15 17:25:57 -07002162 fi.version = sa.getInt(
2163 com.android.internal.R.styleable.AndroidManifestUsesFeature_version, 0);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002164 if (fi.name == null) {
2165 fi.reqGlEsVersion = sa.getInt(
2166 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
2167 FeatureInfo.GL_ES_VERSION_UNDEFINED);
2168 }
2169 if (sa.getBoolean(
2170 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) {
2171 fi.flags |= FeatureInfo.FLAG_REQUIRED;
2172 }
2173 sa.recycle();
2174 return fi;
2175 }
2176
Svet Ganov354cd3c2015-12-17 11:35:04 -08002177 private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
2178 throws XmlPullParserException, IOException {
2179 TypedArray sa = res.obtainAttributes(parser,
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002180 com.android.internal.R.styleable.AndroidManifestUsesPermission);
2181
2182 // Note: don't allow this value to be a reference to a resource
2183 // that may change.
2184 String name = sa.getNonResourceString(
2185 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002186
Christopher Tatefb0676a2013-09-16 16:34:52 -07002187 int maxSdkVersion = 0;
2188 TypedValue val = sa.peekValue(
2189 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
2190 if (val != null) {
2191 if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
2192 maxSdkVersion = val.data;
2193 }
2194 }
2195
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002196 sa.recycle();
2197
Christopher Tatefb0676a2013-09-16 16:34:52 -07002198 if ((maxSdkVersion == 0) || (maxSdkVersion >= Build.VERSION.RESOURCES_SDK_INT)) {
2199 if (name != null) {
2200 int index = pkg.requestedPermissions.indexOf(name);
2201 if (index == -1) {
2202 pkg.requestedPermissions.add(name.intern());
Christopher Tatefb0676a2013-09-16 16:34:52 -07002203 } else {
Svetoslav96a77162015-04-03 13:58:33 -07002204 Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
2205 + name + " in package: " + pkg.packageName + " at: "
2206 + parser.getPositionDescription());
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002207 }
2208 }
2209 }
2210
2211 XmlUtils.skipCurrentTag(parser);
2212 return true;
2213 }
2214
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002215 private static String buildClassName(String pkg, CharSequence clsSeq,
2216 String[] outError) {
2217 if (clsSeq == null || clsSeq.length() <= 0) {
2218 outError[0] = "Empty class name in package " + pkg;
2219 return null;
2220 }
2221 String cls = clsSeq.toString();
2222 char c = cls.charAt(0);
2223 if (c == '.') {
2224 return (pkg + cls).intern();
2225 }
2226 if (cls.indexOf('.') < 0) {
2227 StringBuilder b = new StringBuilder(pkg);
2228 b.append('.');
2229 b.append(cls);
2230 return b.toString().intern();
2231 }
2232 if (c >= 'a' && c <= 'z') {
2233 return cls.intern();
2234 }
2235 outError[0] = "Bad class name " + cls + " in package " + pkg;
2236 return null;
2237 }
2238
2239 private static String buildCompoundName(String pkg,
2240 CharSequence procSeq, String type, String[] outError) {
2241 String proc = procSeq.toString();
2242 char c = proc.charAt(0);
2243 if (pkg != null && c == ':') {
2244 if (proc.length() < 2) {
2245 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
2246 + ": must be at least two characters";
2247 return null;
2248 }
2249 String subName = proc.substring(1);
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002250 String nameError = validateName(subName, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002251 if (nameError != null) {
2252 outError[0] = "Invalid " + type + " name " + proc + " in package "
2253 + pkg + ": " + nameError;
2254 return null;
2255 }
2256 return (pkg + proc).intern();
2257 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002258 String nameError = validateName(proc, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002259 if (nameError != null && !"system".equals(proc)) {
2260 outError[0] = "Invalid " + type + " name " + proc + " in package "
2261 + pkg + ": " + nameError;
2262 return null;
2263 }
2264 return proc.intern();
2265 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002267 private static String buildProcessName(String pkg, String defProc,
2268 CharSequence procSeq, int flags, String[] separateProcesses,
2269 String[] outError) {
2270 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
2271 return defProc != null ? defProc : pkg;
2272 }
2273 if (separateProcesses != null) {
2274 for (int i=separateProcesses.length-1; i>=0; i--) {
2275 String sp = separateProcesses[i];
2276 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
2277 return pkg;
2278 }
2279 }
2280 }
2281 if (procSeq == null || procSeq.length() <= 0) {
2282 return defProc;
2283 }
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002284 return buildCompoundName(pkg, procSeq, "process", outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002285 }
2286
2287 private static String buildTaskAffinityName(String pkg, String defProc,
2288 CharSequence procSeq, String[] outError) {
2289 if (procSeq == null) {
2290 return defProc;
2291 }
2292 if (procSeq.length() <= 0) {
2293 return null;
2294 }
2295 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
2296 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002297
dcashman989eb3712014-06-17 12:56:12 -07002298 private boolean parseKeySets(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002299 XmlResourceParser parser, String[] outError)
Geremy Condraf1bcca82013-01-07 22:35:24 -08002300 throws XmlPullParserException, IOException {
dcashman989eb3712014-06-17 12:56:12 -07002301 // we've encountered the 'key-sets' tag
Geremy Condraf1bcca82013-01-07 22:35:24 -08002302 // all the keys and keysets that we want must be defined here
2303 // so we're going to iterate over the parser and pull out the things we want
2304 int outerDepth = parser.getDepth();
dcashman989eb3712014-06-17 12:56:12 -07002305 int currentKeySetDepth = -1;
Geremy Condraf1bcca82013-01-07 22:35:24 -08002306 int type;
dcashman989eb3712014-06-17 12:56:12 -07002307 String currentKeySet = null;
2308 ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
2309 ArraySet<String> upgradeKeySets = new ArraySet<String>();
2310 ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
2311 ArraySet<String> improperKeySets = new ArraySet<String>();
Geremy Condraf1bcca82013-01-07 22:35:24 -08002312 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2313 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2314 if (type == XmlPullParser.END_TAG) {
dcashman989eb3712014-06-17 12:56:12 -07002315 if (parser.getDepth() == currentKeySetDepth) {
2316 currentKeySet = null;
2317 currentKeySetDepth = -1;
Kenny Root37dca152013-07-10 14:01:49 -07002318 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002319 continue;
2320 }
dcashman989eb3712014-06-17 12:56:12 -07002321 String tagName = parser.getName();
2322 if (tagName.equals("key-set")) {
2323 if (currentKeySet != null) {
dcashman5db0cd42015-05-22 15:24:40 -07002324 outError[0] = "Improperly nested 'key-set' tag at "
2325 + parser.getPositionDescription();
2326 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002327 return false;
2328 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002329 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002330 com.android.internal.R.styleable.AndroidManifestKeySet);
2331 final String keysetName = sa.getNonResourceString(
2332 com.android.internal.R.styleable.AndroidManifestKeySet_name);
2333 definedKeySets.put(keysetName, new ArraySet<String>());
2334 currentKeySet = keysetName;
2335 currentKeySetDepth = parser.getDepth();
2336 sa.recycle();
2337 } else if (tagName.equals("public-key")) {
2338 if (currentKeySet == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002339 outError[0] = "Improperly nested 'key-set' tag at "
2340 + parser.getPositionDescription();
2341 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002342 return false;
2343 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002344 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002345 com.android.internal.R.styleable.AndroidManifestPublicKey);
2346 final String publicKeyName = sa.getNonResourceString(
2347 com.android.internal.R.styleable.AndroidManifestPublicKey_name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002348 final String encodedKey = sa.getNonResourceString(
dcashman989eb3712014-06-17 12:56:12 -07002349 com.android.internal.R.styleable.AndroidManifestPublicKey_value);
2350 if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002351 outError[0] = "'public-key' " + publicKeyName + " must define a public-key value"
2352 + " on first use at " + parser.getPositionDescription();
2353 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Kenny Root37dca152013-07-10 14:01:49 -07002354 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002355 return false;
2356 } else if (encodedKey != null) {
2357 PublicKey currentKey = parsePublicKey(encodedKey);
2358 if (currentKey == null) {
2359 Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
2360 + parser.getPositionDescription() + " key-set " + currentKeySet
2361 + " will not be added to the package's defined key-sets.");
2362 sa.recycle();
2363 improperKeySets.add(currentKeySet);
2364 XmlUtils.skipCurrentTag(parser);
2365 continue;
2366 }
2367 if (publicKeys.get(publicKeyName) == null
2368 || publicKeys.get(publicKeyName).equals(currentKey)) {
2369
2370 /* public-key first definition, or matches old definition */
2371 publicKeys.put(publicKeyName, currentKey);
2372 } else {
dcashman5db0cd42015-05-22 15:24:40 -07002373 outError[0] = "Value of 'public-key' " + publicKeyName
dcashman989eb3712014-06-17 12:56:12 -07002374 + " conflicts with previously defined value at "
dcashman5db0cd42015-05-22 15:24:40 -07002375 + parser.getPositionDescription();
2376 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002377 sa.recycle();
2378 return false;
2379 }
Kenny Root37dca152013-07-10 14:01:49 -07002380 }
dcashman989eb3712014-06-17 12:56:12 -07002381 definedKeySets.get(currentKeySet).add(publicKeyName);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002382 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002383 XmlUtils.skipCurrentTag(parser);
2384 } else if (tagName.equals("upgrade-key-set")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002385 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002386 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
2387 String name = sa.getNonResourceString(
2388 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
2389 upgradeKeySets.add(name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002390 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002391 XmlUtils.skipCurrentTag(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002392 } else if (RIGID_PARSER) {
dcashman5db0cd42015-05-22 15:24:40 -07002393 outError[0] = "Bad element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08002394 + " at " + mArchiveSourcePath + " "
dcashman5db0cd42015-05-22 15:24:40 -07002395 + parser.getPositionDescription();
2396 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Geremy Condraf1bcca82013-01-07 22:35:24 -08002397 return false;
2398 } else {
dcashman989eb3712014-06-17 12:56:12 -07002399 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08002400 + " at " + mArchiveSourcePath + " "
2401 + parser.getPositionDescription());
2402 XmlUtils.skipCurrentTag(parser);
2403 continue;
2404 }
2405 }
dcashman989eb3712014-06-17 12:56:12 -07002406 Set<String> publicKeyNames = publicKeys.keySet();
2407 if (publicKeyNames.removeAll(definedKeySets.keySet())) {
dcashman5db0cd42015-05-22 15:24:40 -07002408 outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
2409 + "'key-set' and 'public-key' names must be distinct.";
2410 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002411 return false;
2412 }
2413 owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
2414 for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) {
2415 final String keySetName = e.getKey();
2416 if (e.getValue().size() == 0) {
2417 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
2418 + "'key-set' " + keySetName + " has no valid associated 'public-key'."
2419 + " Not including in package's defined key-sets.");
2420 continue;
2421 } else if (improperKeySets.contains(keySetName)) {
2422 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
2423 + "'key-set' " + keySetName + " contained improper 'public-key'"
2424 + " tags. Not including in package's defined key-sets.");
2425 continue;
2426 }
2427 owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
2428 for (String s : e.getValue()) {
2429 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
Geremy Condraf1bcca82013-01-07 22:35:24 -08002430 }
2431 }
dcashman989eb3712014-06-17 12:56:12 -07002432 if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
2433 owner.mUpgradeKeySets = upgradeKeySets;
2434 } else {
dcashman5db0cd42015-05-22 15:24:40 -07002435 outError[0] ="Package" + owner.packageName + " AndroidManifext.xml "
2436 + "does not define all 'upgrade-key-set's .";
2437 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002438 return false;
2439 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002440 return true;
2441 }
2442
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07002443 private PermissionGroup parsePermissionGroup(Package owner, int flags, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002444 XmlResourceParser parser, String[] outError)
2445 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002446 PermissionGroup perm = new PermissionGroup(owner);
2447
Svet Ganov354cd3c2015-12-17 11:35:04 -08002448 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002449 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
2450
2451 if (!parsePackageItemInfo(owner, perm.info, outError,
2452 "<permission-group>", sa,
2453 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
2454 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002455 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
Jose Limaf78e3122014-03-06 12:13:15 -08002456 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
2457 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002458 sa.recycle();
2459 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2460 return null;
2461 }
2462
2463 perm.info.descriptionRes = sa.getResourceId(
2464 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
2465 0);
Dianne Hackborn7454d3b2012-09-12 17:22:00 -07002466 perm.info.flags = sa.getInt(
2467 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07002468 perm.info.priority = sa.getInt(
2469 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
Dianne Hackborn99222d22012-05-06 16:30:15 -07002470 if (perm.info.priority > 0 && (flags&PARSE_IS_SYSTEM) == 0) {
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07002471 perm.info.priority = 0;
2472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002473
2474 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002475
Svet Ganov354cd3c2015-12-17 11:35:04 -08002476 if (!parseAllMetaData(res, parser, "<permission-group>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002477 outError)) {
2478 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2479 return null;
2480 }
2481
2482 owner.permissionGroups.add(perm);
2483
2484 return perm;
2485 }
2486
2487 private Permission parsePermission(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002488 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002489 throws XmlPullParserException, IOException {
2490 Permission perm = new Permission(owner);
2491
Svet Ganov354cd3c2015-12-17 11:35:04 -08002492 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002493 com.android.internal.R.styleable.AndroidManifestPermission);
2494
2495 if (!parsePackageItemInfo(owner, perm.info, outError,
2496 "<permission>", sa,
2497 com.android.internal.R.styleable.AndroidManifestPermission_name,
2498 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002499 com.android.internal.R.styleable.AndroidManifestPermission_icon,
Jose Limaf78e3122014-03-06 12:13:15 -08002500 com.android.internal.R.styleable.AndroidManifestPermission_logo,
2501 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002502 sa.recycle();
2503 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2504 return null;
2505 }
2506
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002507 // Note: don't allow this value to be a reference to a resource
2508 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002509 perm.info.group = sa.getNonResourceString(
2510 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
2511 if (perm.info.group != null) {
2512 perm.info.group = perm.info.group.intern();
2513 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002515 perm.info.descriptionRes = sa.getResourceId(
2516 com.android.internal.R.styleable.AndroidManifestPermission_description,
2517 0);
2518
2519 perm.info.protectionLevel = sa.getInt(
2520 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
2521 PermissionInfo.PROTECTION_NORMAL);
2522
Dianne Hackborn2ca2c872012-09-16 16:03:36 -07002523 perm.info.flags = sa.getInt(
2524 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
2525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002526 sa.recycle();
Dianne Hackborne639da72012-02-21 15:11:13 -08002527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528 if (perm.info.protectionLevel == -1) {
2529 outError[0] = "<permission> does not specify protectionLevel";
2530 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2531 return null;
2532 }
Dianne Hackborne639da72012-02-21 15:11:13 -08002533
2534 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
2535
2536 if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_FLAGS) != 0) {
2537 if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
2538 PermissionInfo.PROTECTION_SIGNATURE) {
2539 outError[0] = "<permission> protectionLevel specifies a flag but is "
2540 + "not based on signature type";
2541 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2542 return null;
2543 }
2544 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002545
Svet Ganov354cd3c2015-12-17 11:35:04 -08002546 if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002547 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2548 return null;
2549 }
2550
2551 owner.permissions.add(perm);
2552
2553 return perm;
2554 }
2555
2556 private Permission parsePermissionTree(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002557 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002558 throws XmlPullParserException, IOException {
2559 Permission perm = new Permission(owner);
2560
Svet Ganov354cd3c2015-12-17 11:35:04 -08002561 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 com.android.internal.R.styleable.AndroidManifestPermissionTree);
2563
2564 if (!parsePackageItemInfo(owner, perm.info, outError,
2565 "<permission-tree>", sa,
2566 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
2567 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002568 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
Jose Limaf78e3122014-03-06 12:13:15 -08002569 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
2570 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002571 sa.recycle();
2572 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2573 return null;
2574 }
2575
2576 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002577
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002578 int index = perm.info.name.indexOf('.');
2579 if (index > 0) {
2580 index = perm.info.name.indexOf('.', index+1);
2581 }
2582 if (index < 0) {
2583 outError[0] = "<permission-tree> name has less than three segments: "
2584 + perm.info.name;
2585 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2586 return null;
2587 }
2588
2589 perm.info.descriptionRes = 0;
2590 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
2591 perm.tree = true;
2592
Svet Ganov354cd3c2015-12-17 11:35:04 -08002593 if (!parseAllMetaData(res, parser, "<permission-tree>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002594 outError)) {
2595 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2596 return null;
2597 }
2598
2599 owner.permissions.add(perm);
2600
2601 return perm;
2602 }
2603
2604 private Instrumentation parseInstrumentation(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002605 XmlResourceParser parser, String[] outError)
2606 throws XmlPullParserException, IOException {
2607 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002608 com.android.internal.R.styleable.AndroidManifestInstrumentation);
2609
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002610 if (mParseInstrumentationArgs == null) {
2611 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
2612 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
2613 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002614 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
Jose Limaf78e3122014-03-06 12:13:15 -08002615 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
2616 com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002617 mParseInstrumentationArgs.tag = "<instrumentation>";
2618 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002619
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002620 mParseInstrumentationArgs.sa = sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002621
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002622 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
2623 new InstrumentationInfo());
2624 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002625 sa.recycle();
2626 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2627 return null;
2628 }
2629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002630 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002631 // Note: don't allow this value to be a reference to a resource
2632 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002633 str = sa.getNonResourceString(
2634 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
2635 a.info.targetPackage = str != null ? str.intern() : null;
2636
2637 a.info.handleProfiling = sa.getBoolean(
2638 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
2639 false);
2640
2641 a.info.functionalTest = sa.getBoolean(
2642 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
2643 false);
2644
2645 sa.recycle();
2646
2647 if (a.info.targetPackage == null) {
2648 outError[0] = "<instrumentation> does not specify targetPackage";
2649 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2650 return null;
2651 }
2652
Svet Ganov354cd3c2015-12-17 11:35:04 -08002653 if (!parseAllMetaData(res, parser, "<instrumentation>", a,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002654 outError)) {
2655 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2656 return null;
2657 }
2658
2659 owner.instrumentation.add(a);
2660
2661 return a;
2662 }
2663
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002664 /**
2665 * Parse the {@code application} XML tree at the current parse location in a
2666 * <em>base APK</em> manifest.
2667 * <p>
2668 * When adding new features, carefully consider if they should also be
2669 * supported by split APKs.
2670 */
2671 private boolean parseBaseApplication(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002672 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002673 throws XmlPullParserException, IOException {
2674 final ApplicationInfo ai = owner.applicationInfo;
2675 final String pkgName = owner.applicationInfo.packageName;
2676
Svet Ganov354cd3c2015-12-17 11:35:04 -08002677 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002678 com.android.internal.R.styleable.AndroidManifestApplication);
2679
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002680 String name = sa.getNonConfigurationString(
2681 com.android.internal.R.styleable.AndroidManifestApplication_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002682 if (name != null) {
2683 ai.className = buildClassName(pkgName, name, outError);
2684 if (ai.className == null) {
2685 sa.recycle();
2686 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2687 return false;
2688 }
2689 }
2690
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002691 String manageSpaceActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002692 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
2693 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002694 if (manageSpaceActivity != null) {
2695 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
2696 outError);
2697 }
2698
Christopher Tate181fafa2009-05-14 11:12:14 -07002699 boolean allowBackup = sa.getBoolean(
2700 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
2701 if (allowBackup) {
2702 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07002703
Christopher Tate43fbc5f2016-02-17 18:00:48 -08002704 // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
2705 // and restoreAnyVersion are only relevant if backup is possible for the
2706 // given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002707 String backupAgent = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002708 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
2709 Configuration.NATIVE_CONFIG_VERSION);
Christopher Tate181fafa2009-05-14 11:12:14 -07002710 if (backupAgent != null) {
2711 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07002712 if (DEBUG_BACKUP) {
2713 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002714 + " from " + pkgName + "+" + backupAgent);
2715 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07002716
2717 if (sa.getBoolean(
2718 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
2719 true)) {
2720 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
2721 }
2722 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08002723 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
2724 false)) {
2725 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
2726 }
Christopher Tated1de2562014-06-17 17:12:35 -07002727 if (sa.getBoolean(
2728 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
2729 false)) {
2730 ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
2731 }
Christopher Tate43fbc5f2016-02-17 18:00:48 -08002732 if (sa.getBoolean(
2733 com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
2734 false)) {
2735 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
2736 }
Christopher Tate181fafa2009-05-14 11:12:14 -07002737 }
Matthew Williams303650c2015-04-17 18:22:51 -07002738
2739 TypedValue v = sa.peekValue(
2740 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
2741 if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
2742 if (DEBUG_BACKUP) {
2743 Slog.v(TAG, "fullBackupContent specified as boolean=" +
2744 (v.data == 0 ? "false" : "true"));
2745 }
2746 // "false" => -1, "true" => 0
2747 ai.fullBackupContent = (v.data == 0 ? -1 : 0);
2748 }
2749 if (DEBUG_BACKUP) {
2750 Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
2751 }
Christopher Tate181fafa2009-05-14 11:12:14 -07002752 }
Christopher Tate4a627c72011-04-01 14:43:32 -07002753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002754 TypedValue v = sa.peekValue(
2755 com.android.internal.R.styleable.AndroidManifestApplication_label);
2756 if (v != null && (ai.labelRes=v.resourceId) == 0) {
2757 ai.nonLocalizedLabel = v.coerceToString();
2758 }
2759
2760 ai.icon = sa.getResourceId(
2761 com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
Adam Powell81cd2e92010-04-21 16:35:18 -07002762 ai.logo = sa.getResourceId(
2763 com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);
Jose Limaf78e3122014-03-06 12:13:15 -08002764 ai.banner = sa.getResourceId(
2765 com.android.internal.R.styleable.AndroidManifestApplication_banner, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002766 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08002767 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002768 ai.descriptionRes = sa.getResourceId(
2769 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
2770
2771 if ((flags&PARSE_IS_SYSTEM) != 0) {
2772 if (sa.getBoolean(
2773 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
2774 false)) {
2775 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
2776 }
Amith Yamasani0d8750d2013-05-01 15:25:28 -07002777 }
2778
2779 if (sa.getBoolean(
2780 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
2781 false)) {
2782 owner.mRequiredForAllUsers = true;
Amith Yamasanie993ae12013-04-15 13:42:57 -07002783 }
2784
2785 String restrictedAccountType = sa.getString(com.android.internal.R.styleable
2786 .AndroidManifestApplication_restrictedAccountType);
2787 if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
2788 owner.mRestrictedAccountType = restrictedAccountType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002789 }
2790
Amith Yamasaniccbe3892013-04-12 17:52:42 -07002791 String requiredAccountType = sa.getString(com.android.internal.R.styleable
2792 .AndroidManifestApplication_requiredAccountType);
2793 if (requiredAccountType != null && requiredAccountType.length() > 0) {
2794 owner.mRequiredAccountType = requiredAccountType;
2795 }
2796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002797 if (sa.getBoolean(
2798 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
2799 false)) {
2800 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
2801 }
2802
2803 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07002804 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08002805 false)) {
2806 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
2807 }
2808
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002809 owner.baseHardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07002810 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07002811 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Alan Viveretted70b9e72015-05-27 14:29:20 -07002812 if (owner.baseHardwareAccelerated) {
2813 ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
2814 }
Romain Guy812ccbe2010-06-01 14:07:24 -07002815
2816 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002817 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
2818 true)) {
2819 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
2820 }
2821
2822 if (sa.getBoolean(
2823 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
2824 false)) {
2825 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
2826 }
2827
2828 if (sa.getBoolean(
2829 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
2830 true)) {
2831 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
2832 }
2833
Svet Ganov354cd3c2015-12-17 11:35:04 -08002834 // The parent package controls installation, hence specify test only installs.
2835 if (owner.parentPackage == null) {
2836 if (sa.getBoolean(
2837 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
2838 false)) {
2839 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
2840 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07002841 }
2842
Jason parksa3cdaa52011-01-13 14:15:43 -06002843 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08002844 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06002845 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08002846 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06002847 }
2848
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07002849 if (sa.getBoolean(
Alex Klyubin01a959d2015-03-18 10:05:45 -07002850 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
2851 true)) {
2852 ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
2853 }
2854
2855 if (sa.getBoolean(
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07002856 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
2857 false /* default is no RTL support*/)) {
2858 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
2859 }
2860
Narayan Kamath589a1bc2014-07-03 14:43:26 +01002861 if (sa.getBoolean(
2862 com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
2863 false)) {
2864 ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
2865 }
2866
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07002867 if (sa.getBoolean(
2868 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
2869 true)) {
2870 ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
2871 }
2872
Jeff Sharkey8a372a02016-03-16 16:25:45 -06002873 if (sa.getBoolean(R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
2874 false) && (flags & PARSE_IS_SYSTEM) != 0) {
2875 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
Jeff Sharkeye17ac152015-11-06 22:40:29 -08002876 }
Jeff Sharkey8a372a02016-03-16 16:25:45 -06002877 if (sa.getBoolean(R.styleable.AndroidManifestApplication_directBootAware, false)
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002878 && (flags & PARSE_IS_SYSTEM) != 0) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06002879 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002880 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08002881
Wale Ogunwale6afdf912016-01-30 13:01:33 -08002882 if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity,
2883 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N)) {
2884 ai.privateFlags |= PRIVATE_FLAG_RESIZEABLE_ACTIVITIES;
2885 }
2886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002887 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002888 str = sa.getNonConfigurationString(
2889 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002890 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
2891
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002892 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
2893 str = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002894 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
2895 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002896 } else {
2897 // Some older apps have been seen to use a resource reference
2898 // here that on older builds was ignored (with a warning). We
2899 // need to continue to do this for them so they don't break.
2900 str = sa.getNonResourceString(
2901 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
2902 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002903 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
2904 str, outError);
2905
2906 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002907 CharSequence pname;
2908 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
2909 pname = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002910 com.android.internal.R.styleable.AndroidManifestApplication_process,
2911 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002912 } else {
2913 // Some older apps have been seen to use a resource reference
2914 // here that on older builds was ignored (with a warning). We
2915 // need to continue to do this for them so they don't break.
2916 pname = sa.getNonResourceString(
2917 com.android.internal.R.styleable.AndroidManifestApplication_process);
2918 }
2919 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002920 flags, mSeparateProcesses, outError);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002921
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002922 ai.enabled = sa.getBoolean(
2923 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002924
Jose Lima12d0b4c2014-03-14 16:55:12 -07002925 if (sa.getBoolean(
2926 com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
2927 ai.flags |= ApplicationInfo.FLAG_IS_GAME;
2928 }
2929
Dianne Hackborn02486b12010-08-26 14:18:37 -07002930 if (false) {
2931 if (sa.getBoolean(
2932 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
2933 false)) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08002934 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07002935
2936 // A heavy-weight application can not be in a custom process.
2937 // We can do direct compare because we intern all strings.
2938 if (ai.processName != null && ai.processName != ai.packageName) {
2939 outError[0] = "cantSaveState applications can not use custom processes";
2940 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07002941 }
2942 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002943 }
2944
Adam Powell269248d2011-08-02 10:26:54 -07002945 ai.uiOptions = sa.getInt(
2946 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
2947
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002948 sa.recycle();
2949
2950 if (outError[0] != null) {
2951 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2952 return false;
2953 }
2954
2955 final int innerDepth = parser.getDepth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002956 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07002957 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2958 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
2959 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002960 continue;
2961 }
2962
2963 String tagName = parser.getName();
2964 if (tagName.equals("activity")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002965 Activity a = parseActivity(owner, res, parser, flags, outError, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002966 owner.baseHardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002967 if (a == null) {
2968 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2969 return false;
2970 }
2971
2972 owner.activities.add(a);
2973
2974 } else if (tagName.equals("receiver")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002975 Activity a = parseActivity(owner, res, parser, flags, outError, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002976 if (a == null) {
2977 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2978 return false;
2979 }
2980
2981 owner.receivers.add(a);
2982
2983 } else if (tagName.equals("service")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002984 Service s = parseService(owner, res, parser, flags, outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002985 if (s == null) {
2986 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2987 return false;
2988 }
2989
2990 owner.services.add(s);
2991
2992 } else if (tagName.equals("provider")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002993 Provider p = parseProvider(owner, res, parser, flags, outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002994 if (p == null) {
2995 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2996 return false;
2997 }
2998
2999 owner.providers.add(p);
3000
3001 } else if (tagName.equals("activity-alias")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003002 Activity a = parseActivityAlias(owner, res, parser, flags, outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003003 if (a == null) {
3004 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3005 return false;
3006 }
3007
3008 owner.activities.add(a);
3009
3010 } else if (parser.getName().equals("meta-data")) {
3011 // note: application meta-data is stored off to the side, so it can
3012 // remain null in the primary copy (we like to avoid extra copies because
3013 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003014 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003015 outError)) == null) {
3016 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3017 return false;
3018 }
3019
Dianne Hackbornc895be72013-03-11 17:48:43 -07003020 } else if (tagName.equals("library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003021 sa = res.obtainAttributes(parser,
Dianne Hackbornc895be72013-03-11 17:48:43 -07003022 com.android.internal.R.styleable.AndroidManifestLibrary);
3023
3024 // Note: don't allow this value to be a reference to a resource
3025 // that may change.
3026 String lname = sa.getNonResourceString(
3027 com.android.internal.R.styleable.AndroidManifestLibrary_name);
3028
3029 sa.recycle();
3030
3031 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003032 lname = lname.intern();
3033 if (!ArrayUtils.contains(owner.libraryNames, lname)) {
3034 owner.libraryNames = ArrayUtils.add(owner.libraryNames, lname);
Dianne Hackbornc895be72013-03-11 17:48:43 -07003035 }
3036 }
3037
3038 XmlUtils.skipCurrentTag(parser);
3039
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003040 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003041 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003042 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3043
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003044 // Note: don't allow this value to be a reference to a resource
3045 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003046 String lname = sa.getNonResourceString(
3047 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07003048 boolean req = sa.getBoolean(
3049 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3050 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051
3052 sa.recycle();
3053
Dianne Hackborn49237342009-08-27 20:08:01 -07003054 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003055 lname = lname.intern();
Dianne Hackborn49237342009-08-27 20:08:01 -07003056 if (req) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003057 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07003058 } else {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003059 owner.usesOptionalLibraries = ArrayUtils.add(
3060 owner.usesOptionalLibraries, lname);
3061 }
3062 }
3063
3064 XmlUtils.skipCurrentTag(parser);
3065
3066 } else if (tagName.equals("uses-package")) {
3067 // Dependencies for app installers; we don't currently try to
3068 // enforce this.
3069 XmlUtils.skipCurrentTag(parser);
3070
3071 } else {
3072 if (!RIGID_PARSER) {
3073 Slog.w(TAG, "Unknown element under <application>: " + tagName
3074 + " at " + mArchiveSourcePath + " "
3075 + parser.getPositionDescription());
3076 XmlUtils.skipCurrentTag(parser);
3077 continue;
3078 } else {
3079 outError[0] = "Bad element under <application>: " + tagName;
3080 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3081 return false;
3082 }
3083 }
3084 }
3085
Narayan Kamathb12dcfb2015-03-30 11:31:04 +01003086 modifySharedLibrariesForBackwardCompatibility(owner);
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00003087
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003088 if (hasDomainURLs(owner)) {
3089 owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3090 } else {
3091 owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3092 }
3093
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003094 return true;
3095 }
3096
Narayan Kamathb12dcfb2015-03-30 11:31:04 +01003097 private static void modifySharedLibrariesForBackwardCompatibility(Package owner) {
3098 // "org.apache.http.legacy" is now a part of the boot classpath so it doesn't need
3099 // to be an explicit dependency.
3100 //
3101 // A future change will remove this library from the boot classpath, at which point
3102 // all apps that target SDK 21 and earlier will have it automatically added to their
3103 // dependency lists.
3104 owner.usesLibraries = ArrayUtils.remove(owner.usesLibraries, "org.apache.http.legacy");
3105 owner.usesOptionalLibraries = ArrayUtils.remove(owner.usesOptionalLibraries,
3106 "org.apache.http.legacy");
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00003107 }
3108
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003109 /**
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003110 * 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 -07003111 */
3112 private static boolean hasDomainURLs(Package pkg) {
3113 if (pkg == null || pkg.activities == null) return false;
3114 final ArrayList<Activity> activities = pkg.activities;
3115 final int countActivities = activities.size();
3116 for (int n=0; n<countActivities; n++) {
3117 Activity activity = activities.get(n);
3118 ArrayList<ActivityIntentInfo> filters = activity.intents;
3119 if (filters == null) continue;
3120 final int countFilters = filters.size();
3121 for (int m=0; m<countFilters; m++) {
3122 ActivityIntentInfo aii = filters.get(m);
3123 if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003124 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003125 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
3126 aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
3127 return true;
3128 }
3129 }
3130 }
3131 return false;
3132 }
3133
3134 /**
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003135 * Parse the {@code application} XML tree at the current parse location in a
3136 * <em>split APK</em> manifest.
3137 * <p>
3138 * Note that split APKs have many more restrictions on what they're capable
3139 * of doing, so many valid features of a base APK have been carefully
3140 * omitted here.
3141 */
Svet Ganov354cd3c2015-12-17 11:35:04 -08003142 private boolean parseSplitApplication(Package owner, Resources res, XmlResourceParser parser,
3143 int flags, int splitIndex, String[] outError)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003144 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003145 TypedArray sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003146 com.android.internal.R.styleable.AndroidManifestApplication);
3147
3148 if (sa.getBoolean(
3149 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
3150 owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
3151 }
3152
3153 final int innerDepth = parser.getDepth();
3154 int type;
3155 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3156 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3157 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3158 continue;
3159 }
3160
3161 String tagName = parser.getName();
3162 if (tagName.equals("activity")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003163 Activity a = parseActivity(owner, res, parser, flags, outError, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003164 owner.baseHardwareAccelerated);
3165 if (a == null) {
3166 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3167 return false;
3168 }
3169
3170 owner.activities.add(a);
3171
3172 } else if (tagName.equals("receiver")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003173 Activity a = parseActivity(owner, res, parser, flags, outError, true, false);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003174 if (a == null) {
3175 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3176 return false;
3177 }
3178
3179 owner.receivers.add(a);
3180
3181 } else if (tagName.equals("service")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003182 Service s = parseService(owner, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003183 if (s == null) {
3184 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3185 return false;
3186 }
3187
3188 owner.services.add(s);
3189
3190 } else if (tagName.equals("provider")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003191 Provider p = parseProvider(owner, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003192 if (p == null) {
3193 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3194 return false;
3195 }
3196
3197 owner.providers.add(p);
3198
3199 } else if (tagName.equals("activity-alias")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003200 Activity a = parseActivityAlias(owner, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003201 if (a == null) {
3202 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3203 return false;
3204 }
3205
3206 owner.activities.add(a);
3207
3208 } else if (parser.getName().equals("meta-data")) {
3209 // note: application meta-data is stored off to the side, so it can
3210 // remain null in the primary copy (we like to avoid extra copies because
3211 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003212 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003213 outError)) == null) {
3214 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3215 return false;
3216 }
3217
3218 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003219 sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003220 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3221
3222 // Note: don't allow this value to be a reference to a resource
3223 // that may change.
3224 String lname = sa.getNonResourceString(
3225 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
3226 boolean req = sa.getBoolean(
3227 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3228 true);
3229
3230 sa.recycle();
3231
3232 if (lname != null) {
3233 lname = lname.intern();
3234 if (req) {
3235 // Upgrade to treat as stronger constraint
3236 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
3237 owner.usesOptionalLibraries = ArrayUtils.remove(
3238 owner.usesOptionalLibraries, lname);
3239 } else {
3240 // Ignore if someone already defined as required
3241 if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
3242 owner.usesOptionalLibraries = ArrayUtils.add(
3243 owner.usesOptionalLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07003244 }
3245 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003246 }
3247
3248 XmlUtils.skipCurrentTag(parser);
3249
Dianne Hackborncef65ee2010-09-30 18:27:22 -07003250 } else if (tagName.equals("uses-package")) {
3251 // Dependencies for app installers; we don't currently try to
3252 // enforce this.
3253 XmlUtils.skipCurrentTag(parser);
3254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003255 } else {
3256 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003257 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003258 + " at " + mArchiveSourcePath + " "
3259 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003260 XmlUtils.skipCurrentTag(parser);
3261 continue;
3262 } else {
3263 outError[0] = "Bad element under <application>: " + tagName;
3264 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3265 return false;
3266 }
3267 }
3268 }
3269
3270 return true;
3271 }
3272
3273 private boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
3274 String[] outError, String tag, TypedArray sa,
Jose Limaf78e3122014-03-06 12:13:15 -08003275 int nameRes, int labelRes, int iconRes, int logoRes, int bannerRes) {
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003276 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003277 if (name == null) {
3278 outError[0] = tag + " does not specify android:name";
3279 return false;
3280 }
3281
3282 outInfo.name
3283 = buildClassName(owner.applicationInfo.packageName, name, outError);
3284 if (outInfo.name == null) {
3285 return false;
3286 }
3287
3288 int iconVal = sa.getResourceId(iconRes, 0);
3289 if (iconVal != 0) {
3290 outInfo.icon = iconVal;
3291 outInfo.nonLocalizedLabel = null;
3292 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003293
Adam Powell81cd2e92010-04-21 16:35:18 -07003294 int logoVal = sa.getResourceId(logoRes, 0);
3295 if (logoVal != 0) {
3296 outInfo.logo = logoVal;
3297 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003298
Jose Limaf78e3122014-03-06 12:13:15 -08003299 int bannerVal = sa.getResourceId(bannerRes, 0);
3300 if (bannerVal != 0) {
3301 outInfo.banner = bannerVal;
3302 }
3303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003304 TypedValue v = sa.peekValue(labelRes);
3305 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
3306 outInfo.nonLocalizedLabel = v.coerceToString();
3307 }
3308
3309 outInfo.packageName = owner.packageName;
3310
3311 return true;
3312 }
3313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003314 private Activity parseActivity(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003315 XmlResourceParser parser, int flags, String[] outError,
Romain Guy529b60a2010-08-03 18:05:47 -07003316 boolean receiver, boolean hardwareAccelerated)
3317 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003318 TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003320 if (mParseActivityArgs == null) {
3321 mParseActivityArgs = new ParseComponentArgs(owner, outError,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003322 R.styleable.AndroidManifestActivity_name,
3323 R.styleable.AndroidManifestActivity_label,
3324 R.styleable.AndroidManifestActivity_icon,
3325 R.styleable.AndroidManifestActivity_logo,
3326 R.styleable.AndroidManifestActivity_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003327 mSeparateProcesses,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003328 R.styleable.AndroidManifestActivity_process,
3329 R.styleable.AndroidManifestActivity_description,
3330 R.styleable.AndroidManifestActivity_enabled);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003331 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003332
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003333 mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
3334 mParseActivityArgs.sa = sa;
3335 mParseActivityArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003336
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003337 Activity a = new Activity(mParseActivityArgs, new ActivityInfo());
3338 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003339 sa.recycle();
3340 return null;
3341 }
3342
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003343 boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344 if (setExported) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003345 a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003346 }
3347
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003348 a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003349
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003350 a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
Adam Powell269248d2011-08-02 10:26:54 -07003351 a.info.applicationInfo.uiOptions);
3352
Adam Powelldd8fab22012-03-22 17:47:27 -07003353 String parentName = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003354 R.styleable.AndroidManifestActivity_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003355 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07003356 if (parentName != null) {
3357 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
3358 if (outError[0] == null) {
3359 a.info.parentActivityName = parentClassName;
3360 } else {
3361 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
3362 parentName);
3363 outError[0] = null;
3364 }
3365 }
3366
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003367 String str;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003368 str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003369 if (str == null) {
3370 a.info.permission = owner.applicationInfo.permission;
3371 } else {
3372 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
3373 }
3374
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003375 str = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003376 R.styleable.AndroidManifestActivity_taskAffinity,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003377 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003378 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
3379 owner.applicationInfo.taskAffinity, str, outError);
3380
3381 a.info.flags = 0;
3382 if (sa.getBoolean(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003383 R.styleable.AndroidManifestActivity_multiprocess, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003384 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
3385 }
3386
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003387 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003388 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
3389 }
3390
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003391 if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003392 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
3393 }
3394
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003395 if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003396 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
3397 }
3398
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003399 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003400 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
3401 }
3402
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003403 if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003404 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
3405 }
3406
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003407 if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003408 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
3409 }
3410
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003411 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003412 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
3413 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
3414 }
3415
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003416 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
Dianne Hackbornffa42482009-09-23 22:20:11 -07003417 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
3418 }
3419
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07003420 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
3421 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
3422 a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Craig Mautner5962b122012-10-05 14:45:52 -07003423 }
3424
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003425 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
Daniel Sandler613dde42010-06-21 13:46:39 -04003426 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
3427 }
Craig Mautner5962b122012-10-05 14:45:52 -07003428
Fyodor Kupolov4f5de342015-08-25 10:08:45 -07003429 if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
3430 a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
Fyodor Kupolov703d1c42015-01-27 11:59:00 -08003431 }
3432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003433 if (!receiver) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003434 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07003435 hardwareAccelerated)) {
3436 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
3437 }
3438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003439 a.info.launchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003440 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
Craig Mautner2dac0562014-05-06 09:06:44 -07003441 a.info.documentLaunchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003442 R.styleable.AndroidManifestActivity_documentLaunchMode,
Craig Mautner2dac0562014-05-06 09:06:44 -07003443 ActivityInfo.DOCUMENT_LAUNCH_NONE);
Craig Mautnerffcfcaa2014-06-05 09:54:38 -07003444 a.info.maxRecents = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003445 R.styleable.AndroidManifestActivity_maxRecents,
Dianne Hackborn852975d2014-08-22 17:42:43 -07003446 ActivityManager.getDefaultAppRecentsLimitStatic());
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003447 a.info.configChanges = sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448 a.info.softInputMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003449 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
Craig Mautner2dac0562014-05-06 09:06:44 -07003450
Craig Mautner43e52ed2014-06-16 17:18:52 -07003451 a.info.persistableMode = sa.getInteger(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003452 R.styleable.AndroidManifestActivity_persistableMode,
Craig Mautner43e52ed2014-06-16 17:18:52 -07003453 ActivityInfo.PERSIST_ROOT_ONLY);
Craig Mautner2dac0562014-05-06 09:06:44 -07003454
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003455 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07003456 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
3457 }
3458
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003459 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07003460 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
3461 }
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07003462
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003463 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07003464 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
3465 }
Dianne Hackborna4e102e2014-09-04 22:52:27 -07003466
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003467 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
Dianne Hackborna4e102e2014-09-04 22:52:27 -07003468 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
3469 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003470
Wale Ogunwaled26176f2016-01-25 20:04:04 -08003471 a.info.screenOrientation = sa.getInt(
3472 R.styleable.AndroidManifestActivity_screenOrientation,
3473 SCREEN_ORIENTATION_UNSPECIFIED);
Wale Ogunwale6a591362015-10-05 20:18:27 -07003474
Wale Ogunwaled26176f2016-01-25 20:04:04 -08003475 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale163828d2016-02-01 11:48:19 -08003476 final boolean appDefault = (owner.applicationInfo.privateFlags
3477 & PRIVATE_FLAG_RESIZEABLE_ACTIVITIES) != 0;
3478 final boolean resizeable = sa.getBoolean(
3479 R.styleable.AndroidManifestActivity_resizeableActivity, appDefault);
3480
3481 if (resizeable) {
3482 if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
3483 false)) {
3484 a.info.resizeMode = RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
3485 } else {
3486 a.info.resizeMode = RESIZE_MODE_RESIZEABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08003487 }
Wale Ogunwale163828d2016-02-01 11:48:19 -08003488 } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
3489 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale508ff552016-02-15 19:31:50 -08003490 } else if (!a.info.isFixedOrientation() && (a.info.flags & FLAG_IMMERSIVE) == 0) {
Wale Ogunwaled829d362016-02-10 19:24:49 -08003491 a.info.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08003492 }
3493
3494 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
Wale Ogunwaled26176f2016-01-25 20:04:04 -08003495 a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08003496 }
Wale Ogunwaleb60692e2015-10-24 12:35:56 -07003497
Craig Mautner15df08a2015-04-01 12:17:18 -07003498 a.info.lockTaskLaunchMode =
3499 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003500
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003501 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
3502 R.styleable.AndroidManifestActivity_directBootAware,
3503 owner.applicationInfo.isDirectBootAware());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 } else {
3505 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
3506 a.info.configChanges = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003508 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07003509 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003510 if (a.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003511 Slog.w(TAG, "Activity exported request ignored due to singleUser: "
3512 + a.className + " at " + mArchiveSourcePath + " "
3513 + parser.getPositionDescription());
3514 a.info.exported = false;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003515 setExported = true;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003516 }
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003517 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003518
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003519 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
3520 R.styleable.AndroidManifestActivity_directBootAware,
3521 owner.applicationInfo.isDirectBootAware());
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003522 }
3523
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003524 if (a.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07003525 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003526 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07003527 }
3528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003529 sa.recycle();
3530
Alex Klyubinb9f8a522015-02-03 11:12:59 -08003531 if (receiver && (owner.applicationInfo.privateFlags
3532 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07003533 // A heavy-weight application can not have receives in its main process
3534 // We can do direct compare because we intern all strings.
3535 if (a.info.processName == owner.packageName) {
3536 outError[0] = "Heavy-weight applications can not have receivers in main process";
3537 }
3538 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003540 if (outError[0] != null) {
3541 return null;
3542 }
3543
3544 int outerDepth = parser.getDepth();
3545 int type;
3546 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3547 && (type != XmlPullParser.END_TAG
3548 || parser.getDepth() > outerDepth)) {
3549 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3550 continue;
3551 }
3552
3553 if (parser.getName().equals("intent-filter")) {
3554 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Svet Ganov354cd3c2015-12-17 11:35:04 -08003555 if (!parseIntent(res, parser, true, true, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003556 return null;
3557 }
3558 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003559 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07003560 + mArchiveSourcePath + " "
3561 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003562 } else {
3563 a.intents.add(intent);
3564 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07003565 } else if (!receiver && parser.getName().equals("preferred")) {
3566 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Svet Ganov354cd3c2015-12-17 11:35:04 -08003567 if (!parseIntent(res, parser, false, false, intent, outError)) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07003568 return null;
3569 }
3570 if (intent.countActions() == 0) {
3571 Slog.w(TAG, "No actions in preferred at "
3572 + mArchiveSourcePath + " "
3573 + parser.getPositionDescription());
3574 } else {
3575 if (owner.preferredActivityFilters == null) {
3576 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
3577 }
3578 owner.preferredActivityFilters.add(intent);
3579 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003581 if ((a.metaData = parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003582 outError)) == null) {
3583 return null;
3584 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003585 } else if (!receiver && parser.getName().equals("layout")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003586 parseLayout(res, parser, a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003587 } else {
3588 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003589 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003590 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003591 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003592 + " at " + mArchiveSourcePath + " "
3593 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003594 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07003595 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003596 + " at " + mArchiveSourcePath + " "
3597 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003598 }
3599 XmlUtils.skipCurrentTag(parser);
3600 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003601 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07003602 if (receiver) {
3603 outError[0] = "Bad element under <receiver>: " + parser.getName();
3604 } else {
3605 outError[0] = "Bad element under <activity>: " + parser.getName();
3606 }
3607 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003608 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003609 }
3610 }
3611
3612 if (!setExported) {
3613 a.info.exported = a.intents.size() > 0;
3614 }
3615
3616 return a;
3617 }
3618
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003619 private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003620 TypedArray sw = res.obtainAttributes(attrs,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003621 com.android.internal.R.styleable.AndroidManifestLayout);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003622 int width = -1;
3623 float widthFraction = -1f;
3624 int height = -1;
3625 float heightFraction = -1f;
3626 final int widthType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003627 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003628 if (widthType == TypedValue.TYPE_FRACTION) {
3629 widthFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003630 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003631 1, 1, -1);
3632 } else if (widthType == TypedValue.TYPE_DIMENSION) {
3633 width = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003634 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003635 -1);
3636 }
3637 final int heightType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003638 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003639 if (heightType == TypedValue.TYPE_FRACTION) {
3640 heightFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003641 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003642 1, 1, -1);
3643 } else if (heightType == TypedValue.TYPE_DIMENSION) {
3644 height = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003645 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003646 -1);
3647 }
3648 int gravity = sw.getInt(
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003649 com.android.internal.R.styleable.AndroidManifestLayout_gravity,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003650 Gravity.CENTER);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003651 int minimalSize = sw.getDimensionPixelSize(
3652 com.android.internal.R.styleable.AndroidManifestLayout_minimalSize,
3653 -1);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003654 sw.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003655 a.info.layout = new ActivityInfo.Layout(width, widthFraction,
3656 height, heightFraction, gravity, minimalSize);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003657 }
3658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003659 private Activity parseActivityAlias(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003660 XmlResourceParser parser, int flags, String[] outError)
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003661 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003662 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003663 com.android.internal.R.styleable.AndroidManifestActivityAlias);
3664
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003665 String targetActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003666 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
3667 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003668 if (targetActivity == null) {
3669 outError[0] = "<activity-alias> does not specify android:targetActivity";
3670 sa.recycle();
3671 return null;
3672 }
3673
3674 targetActivity = buildClassName(owner.applicationInfo.packageName,
3675 targetActivity, outError);
3676 if (targetActivity == null) {
3677 sa.recycle();
3678 return null;
3679 }
3680
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003681 if (mParseActivityAliasArgs == null) {
3682 mParseActivityAliasArgs = new ParseComponentArgs(owner, outError,
3683 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
3684 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
3685 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07003686 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08003687 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003688 mSeparateProcesses,
3689 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003690 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003691 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
3692 mParseActivityAliasArgs.tag = "<activity-alias>";
3693 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003694
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003695 mParseActivityAliasArgs.sa = sa;
3696 mParseActivityAliasArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003697
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003698 Activity target = null;
3699
3700 final int NA = owner.activities.size();
3701 for (int i=0; i<NA; i++) {
3702 Activity t = owner.activities.get(i);
3703 if (targetActivity.equals(t.info.name)) {
3704 target = t;
3705 break;
3706 }
3707 }
3708
3709 if (target == null) {
3710 outError[0] = "<activity-alias> target activity " + targetActivity
3711 + " not found in manifest";
3712 sa.recycle();
3713 return null;
3714 }
3715
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003716 ActivityInfo info = new ActivityInfo();
3717 info.targetActivity = targetActivity;
3718 info.configChanges = target.info.configChanges;
3719 info.flags = target.info.flags;
3720 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07003721 info.logo = target.info.logo;
Jose Limaf78e3122014-03-06 12:13:15 -08003722 info.banner = target.info.banner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003723 info.labelRes = target.info.labelRes;
3724 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
3725 info.launchMode = target.info.launchMode;
Yao Chen597ad3f2015-06-09 16:00:14 -07003726 info.lockTaskLaunchMode = target.info.lockTaskLaunchMode;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003727 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003728 if (info.descriptionRes == 0) {
3729 info.descriptionRes = target.info.descriptionRes;
3730 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003731 info.screenOrientation = target.info.screenOrientation;
3732 info.taskAffinity = target.info.taskAffinity;
3733 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07003734 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07003735 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07003736 info.parentActivityName = target.info.parentActivityName;
Craig Mautner8307ea72014-09-11 15:03:53 -07003737 info.maxRecents = target.info.maxRecents;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003738 info.layout = target.info.layout;
Wale Ogunwaled26176f2016-01-25 20:04:04 -08003739 info.resizeMode = target.info.resizeMode;
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003740 info.encryptionAware = info.directBootAware = target.info.directBootAware;
Craig Mautner8307ea72014-09-11 15:03:53 -07003741
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003742 Activity a = new Activity(mParseActivityAliasArgs, info);
3743 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003744 sa.recycle();
3745 return null;
3746 }
3747
3748 final boolean setExported = sa.hasValue(
3749 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
3750 if (setExported) {
3751 a.info.exported = sa.getBoolean(
3752 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
3753 }
3754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003755 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003756 str = sa.getNonConfigurationString(
3757 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003758 if (str != null) {
3759 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
3760 }
3761
Adam Powelldd8fab22012-03-22 17:47:27 -07003762 String parentName = sa.getNonConfigurationString(
3763 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003764 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07003765 if (parentName != null) {
3766 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
3767 if (outError[0] == null) {
3768 a.info.parentActivityName = parentClassName;
3769 } else {
3770 Log.e(TAG, "Activity alias " + a.info.name +
3771 " specified invalid parentActivityName " + parentName);
3772 outError[0] = null;
3773 }
3774 }
3775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003776 sa.recycle();
3777
3778 if (outError[0] != null) {
3779 return null;
3780 }
3781
3782 int outerDepth = parser.getDepth();
3783 int type;
3784 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3785 && (type != XmlPullParser.END_TAG
3786 || parser.getDepth() > outerDepth)) {
3787 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3788 continue;
3789 }
3790
3791 if (parser.getName().equals("intent-filter")) {
3792 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Svet Ganov354cd3c2015-12-17 11:35:04 -08003793 if (!parseIntent(res, parser, true, true, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003794 return null;
3795 }
3796 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003797 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07003798 + mArchiveSourcePath + " "
3799 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003800 } else {
3801 a.intents.add(intent);
3802 }
3803 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003804 if ((a.metaData=parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805 outError)) == null) {
3806 return null;
3807 }
3808 } else {
3809 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003810 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003811 + " at " + mArchiveSourcePath + " "
3812 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003813 XmlUtils.skipCurrentTag(parser);
3814 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003815 } else {
3816 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
3817 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003819 }
3820 }
3821
3822 if (!setExported) {
3823 a.info.exported = a.intents.size() > 0;
3824 }
3825
3826 return a;
3827 }
3828
3829 private Provider parseProvider(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003830 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003831 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003832 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003833 com.android.internal.R.styleable.AndroidManifestProvider);
3834
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003835 if (mParseProviderArgs == null) {
3836 mParseProviderArgs = new ParseComponentArgs(owner, outError,
3837 com.android.internal.R.styleable.AndroidManifestProvider_name,
3838 com.android.internal.R.styleable.AndroidManifestProvider_label,
3839 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07003840 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08003841 com.android.internal.R.styleable.AndroidManifestProvider_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003842 mSeparateProcesses,
3843 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003844 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003845 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
3846 mParseProviderArgs.tag = "<provider>";
3847 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003848
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003849 mParseProviderArgs.sa = sa;
3850 mParseProviderArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003851
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003852 Provider p = new Provider(mParseProviderArgs, new ProviderInfo());
3853 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003854 sa.recycle();
3855 return null;
3856 }
3857
Nick Kralevichf097b162012-07-28 12:43:48 -07003858 boolean providerExportedDefault = false;
3859
3860 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
3861 // For compatibility, applications targeting API level 16 or lower
3862 // should have their content providers exported by default, unless they
3863 // specify otherwise.
3864 providerExportedDefault = true;
3865 }
3866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003867 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07003868 com.android.internal.R.styleable.AndroidManifestProvider_exported,
3869 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003870
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003871 String cpname = sa.getNonConfigurationString(
3872 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003873
3874 p.info.isSyncable = sa.getBoolean(
3875 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
3876 false);
3877
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003878 String permission = sa.getNonConfigurationString(
3879 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
3880 String str = sa.getNonConfigurationString(
3881 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003882 if (str == null) {
3883 str = permission;
3884 }
3885 if (str == null) {
3886 p.info.readPermission = owner.applicationInfo.permission;
3887 } else {
3888 p.info.readPermission =
3889 str.length() > 0 ? str.toString().intern() : null;
3890 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003891 str = sa.getNonConfigurationString(
3892 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003893 if (str == null) {
3894 str = permission;
3895 }
3896 if (str == null) {
3897 p.info.writePermission = owner.applicationInfo.permission;
3898 } else {
3899 p.info.writePermission =
3900 str.length() > 0 ? str.toString().intern() : null;
3901 }
3902
3903 p.info.grantUriPermissions = sa.getBoolean(
3904 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
3905 false);
3906
3907 p.info.multiprocess = sa.getBoolean(
3908 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
3909 false);
3910
3911 p.info.initOrder = sa.getInt(
3912 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
3913 0);
3914
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003915 p.info.flags = 0;
3916
3917 if (sa.getBoolean(
3918 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
3919 false)) {
3920 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003921 if (p.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003922 Slog.w(TAG, "Provider exported request ignored due to singleUser: "
3923 + p.className + " at " + mArchiveSourcePath + " "
3924 + parser.getPositionDescription());
3925 p.info.exported = false;
3926 }
3927 }
3928
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003929 p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
3930 R.styleable.AndroidManifestProvider_directBootAware,
3931 owner.applicationInfo.isDirectBootAware());
3932 if (p.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07003933 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003934 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07003935 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003937 sa.recycle();
3938
Alex Klyubinb9f8a522015-02-03 11:12:59 -08003939 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
3940 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07003941 // A heavy-weight application can not have providers in its main process
3942 // We can do direct compare because we intern all strings.
3943 if (p.info.processName == owner.packageName) {
3944 outError[0] = "Heavy-weight applications can not have providers in main process";
3945 return null;
3946 }
3947 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003949 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07003950 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003951 return null;
3952 }
Dianne Hackborn1bc177c2014-12-03 10:20:30 -08003953 if (cpname.length() <= 0) {
3954 outError[0] = "<provider> has empty authorities attribute";
3955 return null;
3956 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003957 p.info.authority = cpname.intern();
3958
Svet Ganov354cd3c2015-12-17 11:35:04 -08003959 if (!parseProviderTags(res, parser, p, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003960 return null;
3961 }
3962
3963 return p;
3964 }
3965
3966 private boolean parseProviderTags(Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003967 XmlResourceParser parser, Provider outInfo, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003968 throws XmlPullParserException, IOException {
3969 int outerDepth = parser.getDepth();
3970 int type;
3971 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3972 && (type != XmlPullParser.END_TAG
3973 || parser.getDepth() > outerDepth)) {
3974 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3975 continue;
3976 }
3977
Jeff Sharkey85f5f812013-10-07 10:16:12 -07003978 if (parser.getName().equals("intent-filter")) {
3979 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
Svet Ganov354cd3c2015-12-17 11:35:04 -08003980 if (!parseIntent(res, parser, true, false, intent, outError)) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07003981 return false;
3982 }
3983 outInfo.intents.add(intent);
3984
3985 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003986 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003987 outInfo.metaData, outError)) == null) {
3988 return false;
3989 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003990
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003991 } else if (parser.getName().equals("grant-uri-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003992 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003993 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
3994
3995 PatternMatcher pa = null;
3996
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003997 String str = sa.getNonConfigurationString(
3998 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003999 if (str != null) {
4000 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
4001 }
4002
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004003 str = sa.getNonConfigurationString(
4004 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004005 if (str != null) {
4006 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
4007 }
4008
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004009 str = sa.getNonConfigurationString(
4010 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004011 if (str != null) {
4012 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4013 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004015 sa.recycle();
4016
4017 if (pa != null) {
4018 if (outInfo.info.uriPermissionPatterns == null) {
4019 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
4020 outInfo.info.uriPermissionPatterns[0] = pa;
4021 } else {
4022 final int N = outInfo.info.uriPermissionPatterns.length;
4023 PatternMatcher[] newp = new PatternMatcher[N+1];
4024 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
4025 newp[N] = pa;
4026 outInfo.info.uriPermissionPatterns = newp;
4027 }
4028 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004029 } else {
4030 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004031 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004032 + parser.getName() + " at " + mArchiveSourcePath + " "
4033 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004034 XmlUtils.skipCurrentTag(parser);
4035 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004036 } else {
4037 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
4038 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004039 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004040 }
4041 XmlUtils.skipCurrentTag(parser);
4042
4043 } else if (parser.getName().equals("path-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004044 TypedArray sa = res.obtainAttributes(parser,
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004045 com.android.internal.R.styleable.AndroidManifestPathPermission);
4046
4047 PathPermission pa = null;
4048
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004049 String permission = sa.getNonConfigurationString(
4050 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
4051 String readPermission = sa.getNonConfigurationString(
4052 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004053 if (readPermission == null) {
4054 readPermission = permission;
4055 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004056 String writePermission = sa.getNonConfigurationString(
4057 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004058 if (writePermission == null) {
4059 writePermission = permission;
4060 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004061
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004062 boolean havePerm = false;
4063 if (readPermission != null) {
4064 readPermission = readPermission.intern();
4065 havePerm = true;
4066 }
4067 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00004068 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004069 havePerm = true;
4070 }
4071
4072 if (!havePerm) {
4073 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004074 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004075 + parser.getName() + " at " + mArchiveSourcePath + " "
4076 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004077 XmlUtils.skipCurrentTag(parser);
4078 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004079 } else {
4080 outError[0] = "No readPermission or writePermssion for <path-permission>";
4081 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004082 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004083 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004084
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004085 String path = sa.getNonConfigurationString(
4086 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004087 if (path != null) {
4088 pa = new PathPermission(path,
4089 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
4090 }
4091
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004092 path = sa.getNonConfigurationString(
4093 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004094 if (path != null) {
4095 pa = new PathPermission(path,
4096 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
4097 }
4098
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004099 path = sa.getNonConfigurationString(
4100 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004101 if (path != null) {
4102 pa = new PathPermission(path,
4103 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
4104 }
4105
4106 sa.recycle();
4107
4108 if (pa != null) {
4109 if (outInfo.info.pathPermissions == null) {
4110 outInfo.info.pathPermissions = new PathPermission[1];
4111 outInfo.info.pathPermissions[0] = pa;
4112 } else {
4113 final int N = outInfo.info.pathPermissions.length;
4114 PathPermission[] newp = new PathPermission[N+1];
4115 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
4116 newp[N] = pa;
4117 outInfo.info.pathPermissions = newp;
4118 }
4119 } else {
4120 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004121 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004122 + parser.getName() + " at " + mArchiveSourcePath + " "
4123 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004124 XmlUtils.skipCurrentTag(parser);
4125 continue;
4126 }
4127 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
4128 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004129 }
4130 XmlUtils.skipCurrentTag(parser);
4131
4132 } else {
4133 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004134 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004135 + parser.getName() + " at " + mArchiveSourcePath + " "
4136 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004137 XmlUtils.skipCurrentTag(parser);
4138 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004139 } else {
4140 outError[0] = "Bad element under <provider>: " + parser.getName();
4141 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004142 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004143 }
4144 }
4145 return true;
4146 }
4147
4148 private Service parseService(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08004149 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004150 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004151 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004152 com.android.internal.R.styleable.AndroidManifestService);
4153
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004154 if (mParseServiceArgs == null) {
4155 mParseServiceArgs = new ParseComponentArgs(owner, outError,
4156 com.android.internal.R.styleable.AndroidManifestService_name,
4157 com.android.internal.R.styleable.AndroidManifestService_label,
4158 com.android.internal.R.styleable.AndroidManifestService_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004159 com.android.internal.R.styleable.AndroidManifestService_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004160 com.android.internal.R.styleable.AndroidManifestService_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004161 mSeparateProcesses,
4162 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004163 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004164 com.android.internal.R.styleable.AndroidManifestService_enabled);
4165 mParseServiceArgs.tag = "<service>";
4166 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004167
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004168 mParseServiceArgs.sa = sa;
4169 mParseServiceArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004170
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004171 Service s = new Service(mParseServiceArgs, new ServiceInfo());
4172 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173 sa.recycle();
4174 return null;
4175 }
4176
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004177 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004178 com.android.internal.R.styleable.AndroidManifestService_exported);
4179 if (setExported) {
4180 s.info.exported = sa.getBoolean(
4181 com.android.internal.R.styleable.AndroidManifestService_exported, false);
4182 }
4183
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004184 String str = sa.getNonConfigurationString(
4185 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004186 if (str == null) {
4187 s.info.permission = owner.applicationInfo.permission;
4188 } else {
4189 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
4190 }
4191
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004192 s.info.flags = 0;
4193 if (sa.getBoolean(
4194 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
4195 false)) {
4196 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
4197 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08004198 if (sa.getBoolean(
4199 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
4200 false)) {
4201 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
4202 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004203 if (sa.getBoolean(
Robert Sesekb9a86662015-12-09 16:22:45 -05004204 com.android.internal.R.styleable.AndroidManifestService_externalService,
4205 false)) {
4206 s.info.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE;
4207 }
4208 if (sa.getBoolean(
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004209 com.android.internal.R.styleable.AndroidManifestService_singleUser,
4210 false)) {
4211 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07004212 if (s.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004213 Slog.w(TAG, "Service exported request ignored due to singleUser: "
4214 + s.className + " at " + mArchiveSourcePath + " "
4215 + parser.getPositionDescription());
4216 s.info.exported = false;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07004217 setExported = true;
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004218 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004219 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004220
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004221 s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
4222 R.styleable.AndroidManifestService_directBootAware,
4223 owner.applicationInfo.isDirectBootAware());
4224 if (s.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004225 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004226 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004227 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004229 sa.recycle();
4230
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004231 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
4232 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004233 // A heavy-weight application can not have services in its main process
4234 // We can do direct compare because we intern all strings.
4235 if (s.info.processName == owner.packageName) {
4236 outError[0] = "Heavy-weight applications can not have services in main process";
4237 return null;
4238 }
4239 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004241 int outerDepth = parser.getDepth();
4242 int type;
4243 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4244 && (type != XmlPullParser.END_TAG
4245 || parser.getDepth() > outerDepth)) {
4246 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4247 continue;
4248 }
4249
4250 if (parser.getName().equals("intent-filter")) {
4251 ServiceIntentInfo intent = new ServiceIntentInfo(s);
Svet Ganov354cd3c2015-12-17 11:35:04 -08004252 if (!parseIntent(res, parser, true, false, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004253 return null;
4254 }
4255
4256 s.intents.add(intent);
4257 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004258 if ((s.metaData=parseMetaData(res, parser, s.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004259 outError)) == null) {
4260 return null;
4261 }
4262 } else {
4263 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004264 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004265 + parser.getName() + " at " + mArchiveSourcePath + " "
4266 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004267 XmlUtils.skipCurrentTag(parser);
4268 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004269 } else {
4270 outError[0] = "Bad element under <service>: " + parser.getName();
4271 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004272 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004273 }
4274 }
4275
4276 if (!setExported) {
4277 s.info.exported = s.intents.size() > 0;
4278 }
4279
4280 return s;
4281 }
4282
Svet Ganov354cd3c2015-12-17 11:35:04 -08004283 private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag,
4284 Component<?> outInfo, String[] outError) throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004285 int outerDepth = parser.getDepth();
4286 int type;
4287 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4288 && (type != XmlPullParser.END_TAG
4289 || parser.getDepth() > outerDepth)) {
4290 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4291 continue;
4292 }
4293
4294 if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004295 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004296 outInfo.metaData, outError)) == null) {
4297 return false;
4298 }
4299 } else {
4300 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004301 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004302 + parser.getName() + " at " + mArchiveSourcePath + " "
4303 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004304 XmlUtils.skipCurrentTag(parser);
4305 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004306 } else {
4307 outError[0] = "Bad element under " + tag + ": " + parser.getName();
4308 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004309 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004310 }
4311 }
4312 return true;
4313 }
4314
4315 private Bundle parseMetaData(Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08004316 XmlResourceParser parser, Bundle data, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004317 throws XmlPullParserException, IOException {
4318
Svet Ganov354cd3c2015-12-17 11:35:04 -08004319 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004320 com.android.internal.R.styleable.AndroidManifestMetaData);
4321
4322 if (data == null) {
4323 data = new Bundle();
4324 }
4325
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004326 String name = sa.getNonConfigurationString(
4327 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004328 if (name == null) {
4329 outError[0] = "<meta-data> requires an android:name attribute";
4330 sa.recycle();
4331 return null;
4332 }
4333
Dianne Hackborn854060af2009-07-09 18:14:31 -07004334 name = name.intern();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004336 TypedValue v = sa.peekValue(
4337 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
4338 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004339 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004340 data.putInt(name, v.resourceId);
4341 } else {
4342 v = sa.peekValue(
4343 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07004344 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004345 if (v != null) {
4346 if (v.type == TypedValue.TYPE_STRING) {
4347 CharSequence cs = v.coerceToString();
Dianne Hackborn854060af2009-07-09 18:14:31 -07004348 data.putString(name, cs != null ? cs.toString().intern() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004349 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
4350 data.putBoolean(name, v.data != 0);
4351 } else if (v.type >= TypedValue.TYPE_FIRST_INT
4352 && v.type <= TypedValue.TYPE_LAST_INT) {
4353 data.putInt(name, v.data);
4354 } else if (v.type == TypedValue.TYPE_FLOAT) {
4355 data.putFloat(name, v.getFloat());
4356 } else {
4357 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004358 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004359 + parser.getName() + " at " + mArchiveSourcePath + " "
4360 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004361 } else {
4362 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
4363 data = null;
4364 }
4365 }
4366 } else {
4367 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
4368 data = null;
4369 }
4370 }
4371
4372 sa.recycle();
4373
4374 XmlUtils.skipCurrentTag(parser);
4375
4376 return data;
4377 }
4378
Kenny Root05ca4c92011-09-15 10:36:25 -07004379 private static VerifierInfo parseVerifier(Resources res, XmlPullParser parser,
Jeff Sharkey275e0852014-06-17 18:18:49 -07004380 AttributeSet attrs, int flags) {
Kenny Root05ca4c92011-09-15 10:36:25 -07004381 final TypedArray sa = res.obtainAttributes(attrs,
4382 com.android.internal.R.styleable.AndroidManifestPackageVerifier);
4383
4384 final String packageName = sa.getNonResourceString(
4385 com.android.internal.R.styleable.AndroidManifestPackageVerifier_name);
4386
4387 final String encodedPublicKey = sa.getNonResourceString(
4388 com.android.internal.R.styleable.AndroidManifestPackageVerifier_publicKey);
4389
4390 sa.recycle();
4391
4392 if (packageName == null || packageName.length() == 0) {
4393 Slog.i(TAG, "verifier package name was null; skipping");
4394 return null;
Kenny Root05ca4c92011-09-15 10:36:25 -07004395 }
4396
Christopher Tate30147332014-04-15 12:57:47 -07004397 final PublicKey publicKey = parsePublicKey(encodedPublicKey);
4398 if (publicKey == null) {
4399 Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
4400 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -08004401 }
4402
Christopher Tate30147332014-04-15 12:57:47 -07004403 return new VerifierInfo(packageName, publicKey);
Geremy Condraf1bcca82013-01-07 22:35:24 -08004404 }
4405
Christopher Tate30147332014-04-15 12:57:47 -07004406 public static final PublicKey parsePublicKey(final String encodedPublicKey) {
4407 if (encodedPublicKey == null) {
dcashman1616f302015-05-29 14:47:23 -07004408 Slog.w(TAG, "Could not parse null public key");
Christopher Tate30147332014-04-15 12:57:47 -07004409 return null;
4410 }
4411
Kenny Root05ca4c92011-09-15 10:36:25 -07004412 EncodedKeySpec keySpec;
4413 try {
4414 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
4415 keySpec = new X509EncodedKeySpec(encoded);
4416 } catch (IllegalArgumentException e) {
dcashman1616f302015-05-29 14:47:23 -07004417 Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07004418 return null;
4419 }
4420
4421 /* First try the key as an RSA key. */
4422 try {
4423 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08004424 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07004425 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07004426 Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07004427 } catch (InvalidKeySpecException e) {
4428 // Not a RSA public key.
4429 }
4430
dcashman1616f302015-05-29 14:47:23 -07004431 /* Now try it as a ECDSA key. */
4432 try {
4433 final KeyFactory keyFactory = KeyFactory.getInstance("EC");
4434 return keyFactory.generatePublic(keySpec);
4435 } catch (NoSuchAlgorithmException e) {
4436 Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build");
4437 } catch (InvalidKeySpecException e) {
4438 // Not a ECDSA public key.
4439 }
4440
Kenny Root05ca4c92011-09-15 10:36:25 -07004441 /* Now try it as a DSA key. */
4442 try {
4443 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08004444 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07004445 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07004446 Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07004447 } catch (InvalidKeySpecException e) {
4448 // Not a DSA public key.
4449 }
4450
dcashman1616f302015-05-29 14:47:23 -07004451 /* Not a supported key type */
Kenny Root05ca4c92011-09-15 10:36:25 -07004452 return null;
4453 }
4454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004455 private static final String ANDROID_RESOURCES
4456 = "http://schemas.android.com/apk/res/android";
4457
Svet Ganov354cd3c2015-12-17 11:35:04 -08004458 private boolean parseIntent(Resources res, XmlResourceParser parser,
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08004459 boolean allowGlobs, boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004460 throws XmlPullParserException, IOException {
4461
Svet Ganov354cd3c2015-12-17 11:35:04 -08004462 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004463 com.android.internal.R.styleable.AndroidManifestIntentFilter);
4464
4465 int priority = sa.getInt(
4466 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004467 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08004468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004469 TypedValue v = sa.peekValue(
4470 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
4471 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4472 outInfo.nonLocalizedLabel = v.coerceToString();
4473 }
4474
4475 outInfo.icon = sa.getResourceId(
4476 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004477
Adam Powell81cd2e92010-04-21 16:35:18 -07004478 outInfo.logo = sa.getResourceId(
4479 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004480
Jose Limaf78e3122014-03-06 12:13:15 -08004481 outInfo.banner = sa.getResourceId(
4482 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
4483
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08004484 if (allowAutoVerify) {
4485 outInfo.setAutoVerify(sa.getBoolean(
4486 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
4487 false));
4488 }
4489
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004490 sa.recycle();
4491
4492 int outerDepth = parser.getDepth();
4493 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07004494 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
4495 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
4496 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004497 continue;
4498 }
4499
4500 String nodeName = parser.getName();
4501 if (nodeName.equals("action")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004502 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004503 ANDROID_RESOURCES, "name");
4504 if (value == null || value == "") {
4505 outError[0] = "No value supplied for <android:name>";
4506 return false;
4507 }
4508 XmlUtils.skipCurrentTag(parser);
4509
4510 outInfo.addAction(value);
4511 } else if (nodeName.equals("category")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004512 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004513 ANDROID_RESOURCES, "name");
4514 if (value == null || value == "") {
4515 outError[0] = "No value supplied for <android:name>";
4516 return false;
4517 }
4518 XmlUtils.skipCurrentTag(parser);
4519
4520 outInfo.addCategory(value);
4521
4522 } else if (nodeName.equals("data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004523 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004524 com.android.internal.R.styleable.AndroidManifestData);
4525
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004526 String str = sa.getNonConfigurationString(
4527 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004528 if (str != null) {
4529 try {
4530 outInfo.addDataType(str);
4531 } catch (IntentFilter.MalformedMimeTypeException e) {
4532 outError[0] = e.toString();
4533 sa.recycle();
4534 return false;
4535 }
4536 }
4537
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004538 str = sa.getNonConfigurationString(
4539 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004540 if (str != null) {
4541 outInfo.addDataScheme(str);
4542 }
4543
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07004544 str = sa.getNonConfigurationString(
4545 com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
4546 if (str != null) {
4547 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
4548 }
4549
4550 str = sa.getNonConfigurationString(
4551 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
4552 if (str != null) {
4553 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
4554 }
4555
4556 str = sa.getNonConfigurationString(
4557 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
4558 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004559 if (!allowGlobs) {
4560 outError[0] = "sspPattern not allowed here; ssp must be literal";
4561 return false;
4562 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07004563 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4564 }
4565
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004566 String host = sa.getNonConfigurationString(
4567 com.android.internal.R.styleable.AndroidManifestData_host, 0);
4568 String port = sa.getNonConfigurationString(
4569 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004570 if (host != null) {
4571 outInfo.addDataAuthority(host, port);
4572 }
4573
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004574 str = sa.getNonConfigurationString(
4575 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004576 if (str != null) {
4577 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
4578 }
4579
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004580 str = sa.getNonConfigurationString(
4581 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004582 if (str != null) {
4583 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
4584 }
4585
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004586 str = sa.getNonConfigurationString(
4587 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004588 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004589 if (!allowGlobs) {
4590 outError[0] = "pathPattern not allowed here; path must be literal";
4591 return false;
4592 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004593 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4594 }
4595
4596 sa.recycle();
4597 XmlUtils.skipCurrentTag(parser);
4598 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004599 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004600 + parser.getName() + " at " + mArchiveSourcePath + " "
4601 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602 XmlUtils.skipCurrentTag(parser);
4603 } else {
4604 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
4605 return false;
4606 }
4607 }
4608
4609 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07004610
4611 if (DEBUG_PARSER) {
4612 final StringBuilder cats = new StringBuilder("Intent d=");
4613 cats.append(outInfo.hasDefault);
4614 cats.append(", cat=");
4615
4616 final Iterator<String> it = outInfo.categoriesIterator();
4617 if (it != null) {
4618 while (it.hasNext()) {
4619 cats.append(' ');
4620 cats.append(it.next());
4621 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004622 }
Kenny Rootd2d29252011-08-08 11:27:57 -07004623 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004624 }
4625
4626 return true;
4627 }
4628
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004629 /**
4630 * Representation of a full package parsed from APK files on disk. A package
4631 * consists of a single base APK, and zero or more split APKs.
4632 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004633 public final static class Package {
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07004634
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004635 public String packageName;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004636
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004637 /** Names of any split APKs, ordered by parsed splitName */
4638 public String[] splitNames;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004639
4640 // TODO: work towards making these paths invariant
Jeff Sharkey275e0852014-06-17 18:18:49 -07004641
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07004642 public String volumeUuid;
4643
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004644 /**
4645 * Path where this package was found on disk. For monolithic packages
4646 * this is path to single base APK file; for cluster packages this is
4647 * path to the cluster directory.
4648 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004649 public String codePath;
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004650
4651 /** Path of base APK */
4652 public String baseCodePath;
4653 /** Paths of any split APKs, ordered by parsed splitName */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004654 public String[] splitCodePaths;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004655
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004656 /** Revision code of base APK */
4657 public int baseRevisionCode;
4658 /** Revision codes of any split APKs, ordered by parsed splitName */
4659 public int[] splitRevisionCodes;
4660
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004661 /** Flags of any split APKs; ordered by parsed splitName */
4662 public int[] splitFlags;
4663
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004664 /**
4665 * Private flags of any split APKs; ordered by parsed splitName.
4666 *
4667 * {@hide}
4668 */
4669 public int[] splitPrivateFlags;
4670
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004671 public boolean baseHardwareAccelerated;
4672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004673 // For now we only support one application per package.
4674 public final ApplicationInfo applicationInfo = new ApplicationInfo();
4675
4676 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
4677 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
4678 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
4679 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
4680 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
4681 public final ArrayList<Service> services = new ArrayList<Service>(0);
4682 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
4683
4684 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
4685
Dianne Hackborn854060af2009-07-09 18:14:31 -07004686 public ArrayList<String> protectedBroadcasts;
Dianne Hackbornc895be72013-03-11 17:48:43 -07004687
Svet Ganov354cd3c2015-12-17 11:35:04 -08004688 public Package parentPackage;
4689 public ArrayList<Package> childPackages;
4690
Dianne Hackbornc895be72013-03-11 17:48:43 -07004691 public ArrayList<String> libraryNames = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07004692 public ArrayList<String> usesLibraries = null;
4693 public ArrayList<String> usesOptionalLibraries = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004694 public String[] usesLibraryFiles = null;
4695
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004696 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
4697
Dianne Hackbornc1552392010-03-03 16:19:01 -08004698 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004699 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08004700 public ArrayList<String> mAdoptPermissions = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004702 // We store the application meta-data independently to avoid multiple unwanted references
4703 public Bundle mAppMetaData = null;
4704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004705 // The version code declared for this package.
4706 public int mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004708 // The version name declared for this package.
4709 public String mVersionName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004711 // The shared user id that this package wants to use.
4712 public String mSharedUserId;
4713
4714 // The shared user label that this package wants to use.
4715 public int mSharedUserLabel;
4716
4717 // Signatures that were read from the package.
Jeff Sharkey275e0852014-06-17 18:18:49 -07004718 public Signature[] mSignatures;
4719 public Certificate[][] mCertificates;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004720
4721 // For use by package manager service for quick lookup of
4722 // preferred up order.
4723 public int mPreferredOrder = 0;
4724
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07004725 // For use by package manager to keep track of when a package was last used.
4726 public long mLastPackageUsageTimeInMills;
4727
Amith Yamasani13593602012-03-22 16:16:17 -07004728 // // User set enabled state.
4729 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
4730 //
4731 // // Whether the package has been stopped.
4732 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004734 // Additional data supplied by callers.
4735 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07004736
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004737 // Applications hardware preferences
4738 public ArrayList<ConfigurationInfo> configPreferences = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004739
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004740 // Applications requested features
Dianne Hackborn49237342009-08-27 20:08:01 -07004741 public ArrayList<FeatureInfo> reqFeatures = null;
4742
Adam Lesinskid3edfde2014-08-08 17:32:44 -07004743 // Applications requested feature groups
4744 public ArrayList<FeatureGroupInfo> featureGroups = null;
4745
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08004746 public int installLocation;
4747
Jeff Hao272bf3a2014-10-08 13:34:43 -07004748 public boolean coreApp;
4749
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08004750 /* An app that's required for all users and cannot be uninstalled for a user */
4751 public boolean mRequiredForAllUsers;
4752
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07004753 /* The restricted account authenticator type that is used by this application */
4754 public String mRestrictedAccountType;
4755
Amith Yamasaniccbe3892013-04-12 17:52:42 -07004756 /* The required account type without which this application will not function */
4757 public String mRequiredAccountType;
4758
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01004759 public String mOverlayTarget;
4760 public int mOverlayPriority;
4761 public boolean mTrustedOverlay;
4762
Geremy Condraf1bcca82013-01-07 22:35:24 -08004763 /**
dcashman989eb3712014-06-17 12:56:12 -07004764 * Data used to feed the KeySetManagerService
Geremy Condraf1bcca82013-01-07 22:35:24 -08004765 */
dcashman989eb3712014-06-17 12:56:12 -07004766 public ArraySet<PublicKey> mSigningKeys;
4767 public ArraySet<String> mUpgradeKeySets;
4768 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -08004769
Narayan Kamath4903f642014-08-11 13:33:45 +01004770 /**
4771 * The install time abi override for this package, if any.
4772 *
4773 * TODO: This seems like a horrible place to put the abiOverride because
4774 * this isn't something the packageParser parsers. However, this fits in with
4775 * the rest of the PackageManager where package scanning randomly pushes
4776 * and prods fields out of {@code this.applicationInfo}.
4777 */
4778 public String cpuAbiOverride;
Selim Gurun2d291d82016-02-05 17:50:53 -08004779 /**
4780 * The install time abi override to choose 32bit abi's when multiple abi's
4781 * are present. This is only meaningfull for multiarch applications.
4782 * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
4783 */
4784 public boolean use32bitAbi;
Narayan Kamath4903f642014-08-11 13:33:45 +01004785
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004786 public Package(String packageName) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07004787 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07004788 applicationInfo.packageName = packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004789 applicationInfo.uid = -1;
4790 }
4791
Svet Ganov354cd3c2015-12-17 11:35:04 -08004792 public void setApplicationVolumeUuid(String volumeUuid) {
4793 this.applicationInfo.volumeUuid = volumeUuid;
4794 if (childPackages != null) {
4795 final int packageCount = childPackages.size();
4796 for (int i = 0; i < packageCount; i++) {
4797 childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
4798 }
4799 }
4800 }
4801
4802 public void setApplicationInfoCodePath(String codePath) {
4803 this.applicationInfo.setCodePath(codePath);
4804 if (childPackages != null) {
4805 final int packageCount = childPackages.size();
4806 for (int i = 0; i < packageCount; i++) {
4807 childPackages.get(i).applicationInfo.setCodePath(codePath);
4808 }
4809 }
4810 }
4811
4812 public void setApplicationInfoResourcePath(String resourcePath) {
4813 this.applicationInfo.setResourcePath(resourcePath);
4814 if (childPackages != null) {
4815 final int packageCount = childPackages.size();
4816 for (int i = 0; i < packageCount; i++) {
4817 childPackages.get(i).applicationInfo.setResourcePath(resourcePath);
4818 }
4819 }
4820 }
4821
4822 public void setApplicationInfoBaseResourcePath(String resourcePath) {
4823 this.applicationInfo.setBaseResourcePath(resourcePath);
4824 if (childPackages != null) {
4825 final int packageCount = childPackages.size();
4826 for (int i = 0; i < packageCount; i++) {
4827 childPackages.get(i).applicationInfo.setBaseResourcePath(resourcePath);
4828 }
4829 }
4830 }
4831
4832 public void setApplicationInfoBaseCodePath(String baseCodePath) {
4833 this.applicationInfo.setBaseCodePath(baseCodePath);
4834 if (childPackages != null) {
4835 final int packageCount = childPackages.size();
4836 for (int i = 0; i < packageCount; i++) {
4837 childPackages.get(i).applicationInfo.setBaseCodePath(baseCodePath);
4838 }
4839 }
4840 }
4841
4842 public boolean hasChildPackage(String packageName) {
4843 final int childCount = (childPackages != null) ? childPackages.size() : 0;
4844 for (int i = 0; i < childCount; i++) {
4845 if (childPackages.get(i).packageName.equals(packageName)) {
4846 return true;
4847 }
4848 }
4849 return false;
4850 }
4851
4852 public void setApplicationInfoSplitCodePaths(String[] splitCodePaths) {
4853 this.applicationInfo.setSplitCodePaths(splitCodePaths);
4854 // Children have no splits
4855 }
4856
4857 public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) {
4858 this.applicationInfo.setSplitResourcePaths(resroucePaths);
4859 // Children have no splits
4860 }
4861
4862 public void setSplitCodePaths(String[] codePaths) {
4863 this.splitCodePaths = codePaths;
4864 }
4865
4866 public void setCodePath(String codePath) {
4867 this.codePath = codePath;
4868 if (childPackages != null) {
4869 final int packageCount = childPackages.size();
4870 for (int i = 0; i < packageCount; i++) {
4871 childPackages.get(i).codePath = codePath;
4872 }
4873 }
4874 }
4875
4876 public void setBaseCodePath(String baseCodePath) {
4877 this.baseCodePath = baseCodePath;
4878 if (childPackages != null) {
4879 final int packageCount = childPackages.size();
4880 for (int i = 0; i < packageCount; i++) {
4881 childPackages.get(i).baseCodePath = baseCodePath;
4882 }
4883 }
4884 }
4885
4886 public void setSignatures(Signature[] signatures) {
4887 this.mSignatures = signatures;
4888 if (childPackages != null) {
4889 final int packageCount = childPackages.size();
4890 for (int i = 0; i < packageCount; i++) {
4891 childPackages.get(i).mSignatures = signatures;
4892 }
4893 }
4894 }
4895
4896 public void setVolumeUuid(String volumeUuid) {
4897 this.volumeUuid = volumeUuid;
4898 if (childPackages != null) {
4899 final int packageCount = childPackages.size();
4900 for (int i = 0; i < packageCount; i++) {
4901 childPackages.get(i).volumeUuid = volumeUuid;
4902 }
4903 }
4904 }
4905
4906 public void setApplicationInfoFlags(int mask, int flags) {
4907 applicationInfo.flags = (applicationInfo.flags & ~mask) | (mask & flags);
4908 if (childPackages != null) {
4909 final int packageCount = childPackages.size();
4910 for (int i = 0; i < packageCount; i++) {
4911 childPackages.get(i).applicationInfo.flags =
4912 (applicationInfo.flags & ~mask) | (mask & flags);
4913 }
4914 }
4915 }
4916
Selim Gurun75827b22016-02-09 10:55:33 -08004917 public void setUse32bitAbi(boolean use32bitAbi) {
Selim Gurun2d291d82016-02-05 17:50:53 -08004918 this.use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08004919 if (childPackages != null) {
4920 final int packageCount = childPackages.size();
4921 for (int i = 0; i < packageCount; i++) {
Selim Gurun2d291d82016-02-05 17:50:53 -08004922 childPackages.get(i).use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08004923 }
4924 }
4925 }
4926
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004927 public List<String> getAllCodePaths() {
Jeff Sharkey275e0852014-06-17 18:18:49 -07004928 ArrayList<String> paths = new ArrayList<>();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004929 paths.add(baseCodePath);
Jeff Sharkey275e0852014-06-17 18:18:49 -07004930 if (!ArrayUtils.isEmpty(splitCodePaths)) {
4931 Collections.addAll(paths, splitCodePaths);
4932 }
4933 return paths;
4934 }
4935
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004936 /**
4937 * Filtered set of {@link #getAllCodePaths()} that excludes
4938 * resource-only APKs.
4939 */
4940 public List<String> getAllCodePathsExcludingResourceOnly() {
4941 ArrayList<String> paths = new ArrayList<>();
4942 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
4943 paths.add(baseCodePath);
4944 }
4945 if (!ArrayUtils.isEmpty(splitCodePaths)) {
4946 for (int i = 0; i < splitCodePaths.length; i++) {
4947 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
4948 paths.add(splitCodePaths[i]);
4949 }
4950 }
4951 }
4952 return paths;
4953 }
4954
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004955 public void setPackageName(String newName) {
4956 packageName = newName;
4957 applicationInfo.packageName = newName;
4958 for (int i=permissions.size()-1; i>=0; i--) {
4959 permissions.get(i).setPackageName(newName);
4960 }
4961 for (int i=permissionGroups.size()-1; i>=0; i--) {
4962 permissionGroups.get(i).setPackageName(newName);
4963 }
4964 for (int i=activities.size()-1; i>=0; i--) {
4965 activities.get(i).setPackageName(newName);
4966 }
4967 for (int i=receivers.size()-1; i>=0; i--) {
4968 receivers.get(i).setPackageName(newName);
4969 }
4970 for (int i=providers.size()-1; i>=0; i--) {
4971 providers.get(i).setPackageName(newName);
4972 }
4973 for (int i=services.size()-1; i>=0; i--) {
4974 services.get(i).setPackageName(newName);
4975 }
4976 for (int i=instrumentation.size()-1; i>=0; i--) {
4977 instrumentation.get(i).setPackageName(newName);
4978 }
4979 }
Dianne Hackborn65696252012-03-05 18:49:21 -08004980
4981 public boolean hasComponentClassName(String name) {
4982 for (int i=activities.size()-1; i>=0; i--) {
4983 if (name.equals(activities.get(i).className)) {
4984 return true;
4985 }
4986 }
4987 for (int i=receivers.size()-1; i>=0; i--) {
4988 if (name.equals(receivers.get(i).className)) {
4989 return true;
4990 }
4991 }
4992 for (int i=providers.size()-1; i>=0; i--) {
4993 if (name.equals(providers.get(i).className)) {
4994 return true;
4995 }
4996 }
4997 for (int i=services.size()-1; i>=0; i--) {
4998 if (name.equals(services.get(i).className)) {
4999 return true;
5000 }
5001 }
5002 for (int i=instrumentation.size()-1; i>=0; i--) {
5003 if (name.equals(instrumentation.get(i).className)) {
5004 return true;
5005 }
5006 }
5007 return false;
5008 }
5009
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08005010 /**
5011 * @hide
5012 */
5013 public boolean isForwardLocked() {
5014 return applicationInfo.isForwardLocked();
5015 }
5016
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08005017 /**
5018 * @hide
5019 */
5020 public boolean isSystemApp() {
5021 return applicationInfo.isSystemApp();
5022 }
5023
5024 /**
5025 * @hide
5026 */
Svet Ganovadc1cf42015-06-15 16:36:24 -07005027 public boolean isPrivilegedApp() {
5028 return applicationInfo.isPrivilegedApp();
5029 }
5030
5031 /**
5032 * @hide
5033 */
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08005034 public boolean isUpdatedSystemApp() {
5035 return applicationInfo.isUpdatedSystemApp();
5036 }
5037
Fyodor Kupolovebcac162015-09-09 15:56:45 -07005038 /**
5039 * @hide
5040 */
5041 public boolean canHaveOatDir() {
5042 // The following app types CANNOT have oat directory
5043 // - non-updated system apps
5044 // - forward-locked apps or apps installed in ASEC containers
5045 return (!isSystemApp() || isUpdatedSystemApp())
5046 && !isForwardLocked() && !applicationInfo.isExternalAsec();
5047 }
5048
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07005049 public boolean isMatch(int flags) {
5050 if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
5051 return isSystemApp();
5052 }
5053 return true;
5054 }
5055
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005056 public String toString() {
5057 return "Package{"
5058 + Integer.toHexString(System.identityHashCode(this))
5059 + " " + packageName + "}";
5060 }
5061 }
5062
5063 public static class Component<II extends IntentInfo> {
5064 public final Package owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005065 public final ArrayList<II> intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005066 public final String className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005067 public Bundle metaData;
5068
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005069 ComponentName componentName;
5070 String componentShortName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005072 public Component(Package _owner) {
5073 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005074 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005075 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005076 }
5077
5078 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
5079 owner = args.owner;
5080 intents = new ArrayList<II>(0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005081 String name = args.sa.getNonConfigurationString(args.nameRes, 0);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005082 if (name == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005083 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005084 args.outError[0] = args.tag + " does not specify android:name";
5085 return;
5086 }
5087
5088 outInfo.name
5089 = buildClassName(owner.applicationInfo.packageName, name, args.outError);
5090 if (outInfo.name == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005091 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005092 args.outError[0] = args.tag + " does not have valid android:name";
5093 return;
5094 }
5095
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005096 className = outInfo.name;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005097
5098 int iconVal = args.sa.getResourceId(args.iconRes, 0);
5099 if (iconVal != 0) {
5100 outInfo.icon = iconVal;
5101 outInfo.nonLocalizedLabel = null;
5102 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005103
Adam Powell81cd2e92010-04-21 16:35:18 -07005104 int logoVal = args.sa.getResourceId(args.logoRes, 0);
5105 if (logoVal != 0) {
5106 outInfo.logo = logoVal;
5107 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005108
Jose Limaf78e3122014-03-06 12:13:15 -08005109 int bannerVal = args.sa.getResourceId(args.bannerRes, 0);
5110 if (bannerVal != 0) {
5111 outInfo.banner = bannerVal;
5112 }
5113
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005114 TypedValue v = args.sa.peekValue(args.labelRes);
5115 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
5116 outInfo.nonLocalizedLabel = v.coerceToString();
5117 }
5118
5119 outInfo.packageName = owner.packageName;
5120 }
5121
5122 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
5123 this(args, (PackageItemInfo)outInfo);
5124 if (args.outError[0] != null) {
5125 return;
5126 }
5127
5128 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07005129 CharSequence pname;
5130 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07005131 pname = args.sa.getNonConfigurationString(args.processRes,
5132 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07005133 } else {
5134 // Some older apps have been seen to use a resource reference
5135 // here that on older builds was ignored (with a warning). We
5136 // need to continue to do this for them so they don't break.
5137 pname = args.sa.getNonResourceString(args.processRes);
5138 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005139 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07005140 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005141 args.flags, args.sepProcesses, args.outError);
5142 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005143
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005144 if (args.descriptionRes != 0) {
5145 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
5146 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005147
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005148 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005149 }
5150
5151 public Component(Component<II> clone) {
5152 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005153 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005154 className = clone.className;
5155 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005156 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005157 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005158
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005159 public ComponentName getComponentName() {
5160 if (componentName != null) {
5161 return componentName;
5162 }
5163 if (className != null) {
5164 componentName = new ComponentName(owner.applicationInfo.packageName,
5165 className);
5166 }
5167 return componentName;
5168 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005169
5170 public void appendComponentShortName(StringBuilder sb) {
5171 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005172 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005173
5174 public void printComponentShortName(PrintWriter pw) {
5175 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
5176 }
5177
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005178 public void setPackageName(String packageName) {
5179 componentName = null;
5180 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005181 }
5182 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005184 public final static class Permission extends Component<IntentInfo> {
5185 public final PermissionInfo info;
5186 public boolean tree;
5187 public PermissionGroup group;
5188
5189 public Permission(Package _owner) {
5190 super(_owner);
5191 info = new PermissionInfo();
5192 }
5193
5194 public Permission(Package _owner, PermissionInfo _info) {
5195 super(_owner);
5196 info = _info;
5197 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005198
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005199 public void setPackageName(String packageName) {
5200 super.setPackageName(packageName);
5201 info.packageName = packageName;
5202 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005203
5204 public String toString() {
5205 return "Permission{"
5206 + Integer.toHexString(System.identityHashCode(this))
5207 + " " + info.name + "}";
5208 }
5209 }
5210
5211 public final static class PermissionGroup extends Component<IntentInfo> {
5212 public final PermissionGroupInfo info;
5213
5214 public PermissionGroup(Package _owner) {
5215 super(_owner);
5216 info = new PermissionGroupInfo();
5217 }
5218
5219 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
5220 super(_owner);
5221 info = _info;
5222 }
5223
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005224 public void setPackageName(String packageName) {
5225 super.setPackageName(packageName);
5226 info.packageName = packageName;
5227 }
5228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005229 public String toString() {
5230 return "PermissionGroup{"
5231 + Integer.toHexString(System.identityHashCode(this))
5232 + " " + info.name + "}";
5233 }
5234 }
5235
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005236 private static boolean copyNeeded(int flags, Package p,
5237 PackageUserState state, Bundle metaData, int userId) {
Xiaohui Chen98404fd2015-08-17 16:09:02 -07005238 if (userId != UserHandle.USER_SYSTEM) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005239 // We always need to copy for other users, since we need
5240 // to fix up the uid.
5241 return true;
5242 }
5243 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
5244 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07005245 if (p.applicationInfo.enabled != enabled) {
5246 return true;
5247 }
5248 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07005249 if (!state.installed || state.hidden) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005250 return true;
5251 }
5252 if (state.stopped) {
5253 return true;
5254 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005255 if ((flags & PackageManager.GET_META_DATA) != 0
5256 && (metaData != null || p.mAppMetaData != null)) {
5257 return true;
5258 }
5259 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
5260 && p.usesLibraryFiles != null) {
5261 return true;
5262 }
5263 return false;
5264 }
5265
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005266 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
5267 PackageUserState state) {
5268 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07005269 }
5270
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08005271 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
5272 PackageUserState state) {
5273 // CompatibilityMode is global state.
5274 if (!sCompatibilityModeEnabled) {
5275 ai.disableCompatibilityMode();
5276 }
5277 if (state.installed) {
5278 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
5279 } else {
5280 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
5281 }
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00005282 if (state.suspended) {
5283 ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
5284 } else {
5285 ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
5286 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07005287 if (state.hidden) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005288 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07005289 } else {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005290 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07005291 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08005292 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
5293 ai.enabled = true;
5294 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
5295 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
5296 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
5297 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
5298 ai.enabled = false;
5299 }
5300 ai.enabledSetting = state.enabled;
5301 }
5302
Amith Yamasani13593602012-03-22 16:16:17 -07005303 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005304 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005305 if (p == null) return null;
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07005306 if (!checkUseInstalledOrHidden(flags, state) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005307 return null;
5308 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08005309 if (!copyNeeded(flags, p, state, null, userId)
5310 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
5311 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
5312 // In this case it is safe to directly modify the internal ApplicationInfo state:
5313 // - CompatibilityMode is global state, so will be the same for every call.
5314 // - We only come in to here if the app should reported as installed; this is the
5315 // default state, and we will do a copy otherwise.
5316 // - The enable state will always be reported the same for the application across
5317 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
5318 // be doing a copy.
5319 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005320 return p.applicationInfo;
5321 }
5322
5323 // Make shallow copy so we can store the metadata/libraries safely
5324 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Jeff Sharkey15447792015-11-05 16:18:51 -08005325 ai.initForUser(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005326 if ((flags & PackageManager.GET_META_DATA) != 0) {
5327 ai.metaData = p.mAppMetaData;
5328 }
5329 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
5330 ai.sharedLibraryFiles = p.usesLibraryFiles;
5331 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005332 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07005333 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08005334 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07005335 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08005336 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08005337 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005338 return ai;
5339 }
5340
Dianne Hackbornace27912014-09-18 18:38:30 -07005341 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
5342 PackageUserState state, int userId) {
5343 if (ai == null) return null;
5344 if (!checkUseInstalledOrHidden(flags, state)) {
5345 return null;
5346 }
5347 // This is only used to return the ResolverActivity; we will just always
5348 // make a copy.
5349 ai = new ApplicationInfo(ai);
Jeff Sharkey15447792015-11-05 16:18:51 -08005350 ai.initForUser(userId);
Dianne Hackbornace27912014-09-18 18:38:30 -07005351 if (state.stopped) {
5352 ai.flags |= ApplicationInfo.FLAG_STOPPED;
5353 } else {
5354 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
5355 }
5356 updateApplicationInfo(ai, flags, state);
5357 return ai;
5358 }
5359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005360 public static final PermissionInfo generatePermissionInfo(
5361 Permission p, int flags) {
5362 if (p == null) return null;
5363 if ((flags&PackageManager.GET_META_DATA) == 0) {
5364 return p.info;
5365 }
5366 PermissionInfo pi = new PermissionInfo(p.info);
5367 pi.metaData = p.metaData;
5368 return pi;
5369 }
5370
5371 public static final PermissionGroupInfo generatePermissionGroupInfo(
5372 PermissionGroup pg, int flags) {
5373 if (pg == null) return null;
5374 if ((flags&PackageManager.GET_META_DATA) == 0) {
5375 return pg.info;
5376 }
5377 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
5378 pgi.metaData = pg.metaData;
5379 return pgi;
5380 }
5381
5382 public final static class Activity extends Component<ActivityIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005383 public final ActivityInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005384
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005385 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
5386 super(args, _info);
5387 info = _info;
5388 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005389 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005390
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005391 public void setPackageName(String packageName) {
5392 super.setPackageName(packageName);
5393 info.packageName = packageName;
5394 }
5395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005396 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005397 StringBuilder sb = new StringBuilder(128);
5398 sb.append("Activity{");
5399 sb.append(Integer.toHexString(System.identityHashCode(this)));
5400 sb.append(' ');
5401 appendComponentShortName(sb);
5402 sb.append('}');
5403 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005404 }
5405 }
5406
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005407 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
5408 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005409 if (a == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07005410 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005411 return null;
5412 }
5413 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005414 return a.info;
5415 }
5416 // Make shallow copies so we can store the metadata safely
5417 ActivityInfo ai = new ActivityInfo(a.info);
5418 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005419 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005420 return ai;
5421 }
5422
Dianne Hackbornace27912014-09-18 18:38:30 -07005423 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
5424 PackageUserState state, int userId) {
5425 if (ai == null) return null;
5426 if (!checkUseInstalledOrHidden(flags, state)) {
5427 return null;
5428 }
5429 // This is only used to return the ResolverActivity; we will just always
5430 // make a copy.
5431 ai = new ActivityInfo(ai);
5432 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
5433 return ai;
5434 }
5435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005436 public final static class Service extends Component<ServiceIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005437 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005438
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005439 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
5440 super(args, _info);
5441 info = _info;
5442 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005443 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005444
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005445 public void setPackageName(String packageName) {
5446 super.setPackageName(packageName);
5447 info.packageName = packageName;
5448 }
5449
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005450 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005451 StringBuilder sb = new StringBuilder(128);
5452 sb.append("Service{");
5453 sb.append(Integer.toHexString(System.identityHashCode(this)));
5454 sb.append(' ');
5455 appendComponentShortName(sb);
5456 sb.append('}');
5457 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005458 }
5459 }
5460
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005461 public static final ServiceInfo generateServiceInfo(Service s, int flags,
5462 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005463 if (s == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07005464 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005465 return null;
5466 }
5467 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005468 return s.info;
5469 }
5470 // Make shallow copies so we can store the metadata safely
5471 ServiceInfo si = new ServiceInfo(s.info);
5472 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005473 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005474 return si;
5475 }
5476
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005477 public final static class Provider extends Component<ProviderIntentInfo> {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005478 public final ProviderInfo info;
5479 public boolean syncable;
5480
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005481 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
5482 super(args, _info);
5483 info = _info;
5484 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005485 syncable = false;
5486 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005488 public Provider(Provider existingProvider) {
5489 super(existingProvider);
5490 this.info = existingProvider.info;
5491 this.syncable = existingProvider.syncable;
5492 }
5493
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005494 public void setPackageName(String packageName) {
5495 super.setPackageName(packageName);
5496 info.packageName = packageName;
5497 }
5498
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005499 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005500 StringBuilder sb = new StringBuilder(128);
5501 sb.append("Provider{");
5502 sb.append(Integer.toHexString(System.identityHashCode(this)));
5503 sb.append(' ');
5504 appendComponentShortName(sb);
5505 sb.append('}');
5506 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005507 }
5508 }
5509
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005510 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
5511 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005512 if (p == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07005513 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005514 return null;
5515 }
5516 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005517 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005518 || p.info.uriPermissionPatterns == null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005519 return p.info;
5520 }
5521 // Make shallow copies so we can store the metadata safely
5522 ProviderInfo pi = new ProviderInfo(p.info);
5523 pi.metaData = p.metaData;
5524 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
5525 pi.uriPermissionPatterns = null;
5526 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005527 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005528 return pi;
5529 }
5530
5531 public final static class Instrumentation extends Component {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005532 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005533
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005534 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
5535 super(args, _info);
5536 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005537 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005538
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005539 public void setPackageName(String packageName) {
5540 super.setPackageName(packageName);
5541 info.packageName = packageName;
5542 }
5543
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005544 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005545 StringBuilder sb = new StringBuilder(128);
5546 sb.append("Instrumentation{");
5547 sb.append(Integer.toHexString(System.identityHashCode(this)));
5548 sb.append(' ');
5549 appendComponentShortName(sb);
5550 sb.append('}');
5551 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005552 }
5553 }
5554
5555 public static final InstrumentationInfo generateInstrumentationInfo(
5556 Instrumentation i, int flags) {
5557 if (i == null) return null;
5558 if ((flags&PackageManager.GET_META_DATA) == 0) {
5559 return i.info;
5560 }
5561 InstrumentationInfo ii = new InstrumentationInfo(i.info);
5562 ii.metaData = i.metaData;
5563 return ii;
5564 }
5565
5566 public static class IntentInfo extends IntentFilter {
5567 public boolean hasDefault;
5568 public int labelRes;
5569 public CharSequence nonLocalizedLabel;
5570 public int icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07005571 public int logo;
Jose Limaf78e3122014-03-06 12:13:15 -08005572 public int banner;
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005573 public int preferred;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005574 }
5575
5576 public final static class ActivityIntentInfo extends IntentInfo {
5577 public final Activity activity;
5578
5579 public ActivityIntentInfo(Activity _activity) {
5580 activity = _activity;
5581 }
5582
5583 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005584 StringBuilder sb = new StringBuilder(128);
5585 sb.append("ActivityIntentInfo{");
5586 sb.append(Integer.toHexString(System.identityHashCode(this)));
5587 sb.append(' ');
5588 activity.appendComponentShortName(sb);
5589 sb.append('}');
5590 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005591 }
5592 }
5593
5594 public final static class ServiceIntentInfo extends IntentInfo {
5595 public final Service service;
5596
5597 public ServiceIntentInfo(Service _service) {
5598 service = _service;
5599 }
5600
5601 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005602 StringBuilder sb = new StringBuilder(128);
5603 sb.append("ServiceIntentInfo{");
5604 sb.append(Integer.toHexString(System.identityHashCode(this)));
5605 sb.append(' ');
5606 service.appendComponentShortName(sb);
5607 sb.append('}');
5608 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005609 }
5610 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005611
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005612 public static final class ProviderIntentInfo extends IntentInfo {
5613 public final Provider provider;
5614
5615 public ProviderIntentInfo(Provider provider) {
5616 this.provider = provider;
5617 }
5618
5619 public String toString() {
5620 StringBuilder sb = new StringBuilder(128);
5621 sb.append("ProviderIntentInfo{");
5622 sb.append(Integer.toHexString(System.identityHashCode(this)));
5623 sb.append(' ');
5624 provider.appendComponentShortName(sb);
5625 sb.append('}');
5626 return sb.toString();
5627 }
5628 }
5629
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005630 /**
5631 * @hide
5632 */
5633 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
5634 sCompatibilityModeEnabled = compatibilityModeEnabled;
5635 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005636
Jeff Sharkey275e0852014-06-17 18:18:49 -07005637 private static AtomicReference<byte[]> sBuffer = new AtomicReference<byte[]>();
5638
5639 public static long readFullyIgnoringContents(InputStream in) throws IOException {
5640 byte[] buffer = sBuffer.getAndSet(null);
5641 if (buffer == null) {
5642 buffer = new byte[4096];
5643 }
5644
5645 int n = 0;
5646 int count = 0;
5647 while ((n = in.read(buffer, 0, buffer.length)) != -1) {
5648 count += n;
5649 }
5650
5651 sBuffer.set(buffer);
5652 return count;
5653 }
5654
5655 public static void closeQuietly(StrictJarFile jarFile) {
5656 if (jarFile != null) {
5657 try {
5658 jarFile.close();
5659 } catch (Exception ignored) {
5660 }
5661 }
5662 }
5663
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005664 public static class PackageParserException extends Exception {
5665 public final int error;
5666
5667 public PackageParserException(int error, String detailMessage) {
5668 super(detailMessage);
5669 this.error = error;
5670 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07005671
5672 public PackageParserException(int error, String detailMessage, Throwable throwable) {
5673 super(detailMessage, throwable);
5674 this.error = error;
5675 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005676 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005677}