blob: 808c2628c450e68e85948ab442b140963c38b084 [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
Jeff Sharkey275e0852014-06-17 18:18:49 -070019import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070020import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
Jeff Sharkey275e0852014-06-17 18:18:49 -070021import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
22import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070023import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -070024import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
Jeff Sharkey275e0852014-06-17 18:18:49 -070025import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
26import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
Todd Kennedy27c24fb2015-09-17 16:49:25 -070027import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070028
Dianne Hackborn852975d2014-08-22 17:42:43 -070029import android.app.ActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.content.ComponentName;
31import android.content.Intent;
32import android.content.IntentFilter;
33import android.content.res.AssetManager;
34import android.content.res.Configuration;
35import android.content.res.Resources;
36import android.content.res.TypedArray;
37import android.content.res.XmlResourceParser;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -070038import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.os.Bundle;
Jeff Sharkey6dce4962015-07-03 18:08:41 -070040import android.os.Environment;
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -070041import android.os.FileUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.os.PatternMatcher;
Todd Kennedy27c24fb2015-09-17 16:49:25 -070043import android.os.Trace;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070044import android.os.UserHandle;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -070045import android.text.TextUtils;
Jeff Sharkey275e0852014-06-17 18:18:49 -070046import android.util.ArrayMap;
47import android.util.ArraySet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import android.util.AttributeSet;
Kenny Root05ca4c92011-09-15 10:36:25 -070049import android.util.Base64;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.util.DisplayMetrics;
Kenny Root05ca4c92011-09-15 10:36:25 -070051import android.util.Log;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070052import android.util.Pair;
Kenny Rootd2d29252011-08-08 11:27:57 -070053import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import android.util.TypedValue;
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -070055import android.view.Gravity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -080057import com.android.internal.R;
Jeff Sharkey275e0852014-06-17 18:18:49 -070058import com.android.internal.util.ArrayUtils;
59import com.android.internal.util.XmlUtils;
60
61import libcore.io.IoUtils;
62
63import org.xmlpull.v1.XmlPullParser;
64import org.xmlpull.v1.XmlPullParserException;
65
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import java.io.File;
67import java.io.IOException;
68import java.io.InputStream;
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -070069import java.io.PrintWriter;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070070import java.security.GeneralSecurityException;
Kenny Root05ca4c92011-09-15 10:36:25 -070071import java.security.KeyFactory;
72import java.security.NoSuchAlgorithmException;
73import java.security.PublicKey;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074import java.security.cert.Certificate;
75import java.security.cert.CertificateEncodingException;
Kenny Root05ca4c92011-09-15 10:36:25 -070076import java.security.spec.EncodedKeySpec;
77import java.security.spec.InvalidKeySpecException;
78import java.security.spec.X509EncodedKeySpec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079import java.util.ArrayList;
Dianne Hackbornffcda102014-04-24 13:06:27 -070080import java.util.Arrays;
Jeff Sharkey275e0852014-06-17 18:18:49 -070081import java.util.Collections;
82import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083import java.util.Iterator;
Kenny Root05ca4c92011-09-15 10:36:25 -070084import java.util.List;
Geremy Condraf1bcca82013-01-07 22:35:24 -080085import java.util.Set;
Jeff Sharkey275e0852014-06-17 18:18:49 -070086import java.util.concurrent.atomic.AtomicReference;
Narayan Kamatheb565dc2013-12-12 16:54:33 +000087import java.util.jar.StrictJarFile;
Kenny Root6c918ce2013-04-02 14:04:24 -070088import java.util.zip.ZipEntry;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089
90/**
Jeff Sharkeyda96e132014-07-15 14:54:09 -070091 * Parser for package files (APKs) on disk. This supports apps packaged either
92 * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
93 * APKs in a single directory.
94 * <p>
95 * Apps packaged as multiple APKs always consist of a single "base" APK (with a
96 * {@code null} split name) and zero or more "split" APKs (with unique split
97 * names). Any subset of those split APKs are a valid install, as long as the
98 * following constraints are met:
99 * <ul>
100 * <li>All APKs must have the exact same package name, version code, and signing
101 * certificates.
102 * <li>All APKs must have unique split names.
103 * <li>All installations must contain a single base APK.
104 * </ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700106 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107 */
108public class PackageParser {
Kenny Rootd2d29252011-08-08 11:27:57 -0700109 private static final boolean DEBUG_JAR = false;
110 private static final boolean DEBUG_PARSER = false;
111 private static final boolean DEBUG_BACKUP = false;
112
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700113 // TODO: switch outError users to PackageParserException
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700114 // TODO: refactor "codePath" to "apkPath"
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700115
Kenny Rootbcc954d2011-08-08 16:19:08 -0700116 /** File name in an APK for the Android manifest. */
117 private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
118
Christopher Tatef3d939c2015-09-17 12:25:51 -0700119 /**
120 * File name in an APK for bytecode. There may be additional bytecode files
121 * but this one is always required for an APK that has code.
122 */
123 private static final String BYTECODE_FILENAME = "classes.dex";
124
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700125 /** Path prefix for apps on expanded storage */
126 private static final String MNT_EXPAND = "/mnt/expand/";
127
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700128 /** @hide */
129 public static class NewPermissionInfo {
130 public final String name;
131 public final int sdkVersion;
132 public final int fileVersion;
133
134 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
135 this.name = name;
136 this.sdkVersion = sdkVersion;
137 this.fileVersion = fileVersion;
138 }
139 }
Dianne Hackborn79245122012-03-12 10:51:26 -0700140
141 /** @hide */
142 public static class SplitPermissionInfo {
143 public final String rootPerm;
144 public final String[] newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700145 public final int targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700146
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700147 public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
Dianne Hackborn79245122012-03-12 10:51:26 -0700148 this.rootPerm = rootPerm;
149 this.newPerms = newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700150 this.targetSdk = targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700151 }
152 }
153
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700154 /**
155 * List of new permissions that have been added since 1.0.
156 * NOTE: These must be declared in SDK version order, with permissions
157 * added to older SDKs appearing before those added to newer SDKs.
Dianne Hackborn79245122012-03-12 10:51:26 -0700158 * If sdkVersion is 0, then this is not a permission that we want to
159 * automatically add to older apps, but we do want to allow it to be
160 * granted during a platform update.
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700161 * @hide
162 */
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700163 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
164 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -0700165 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700166 android.os.Build.VERSION_CODES.DONUT, 0),
167 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
168 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700169 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170
Dianne Hackborn79245122012-03-12 10:51:26 -0700171 /**
172 * List of permissions that have been split into more granular or dependent
173 * permissions.
174 * @hide
175 */
176 public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
177 new PackageParser.SplitPermissionInfo[] {
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700178 // READ_EXTERNAL_STORAGE is always required when an app requests
179 // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
180 // write access without read access. The hack here with the target
181 // target SDK version ensures that this grant is always done.
Dianne Hackborn79245122012-03-12 10:51:26 -0700182 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700183 new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700184 android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700185 new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
186 new String[] { android.Manifest.permission.READ_CALL_LOG },
187 android.os.Build.VERSION_CODES.JELLY_BEAN),
188 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
189 new String[] { android.Manifest.permission.WRITE_CALL_LOG },
190 android.os.Build.VERSION_CODES.JELLY_BEAN)
Dianne Hackborn79245122012-03-12 10:51:26 -0700191 };
192
Jeff Sharkey275e0852014-06-17 18:18:49 -0700193 /**
194 * @deprecated callers should move to explicitly passing around source path.
195 */
196 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 private String mArchiveSourcePath;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700200 private boolean mOnlyCoreApps;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700201 private DisplayMetrics mMetrics;
202
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700203 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700204 private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205
206 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
207
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700208 private static boolean sCompatibilityModeEnabled = true;
Amith Yamasani655d0e22013-06-12 14:19:10 -0700209 private static final int PARSE_DEFAULT_INSTALL_LOCATION =
210 PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700211
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700212 static class ParsePackageItemArgs {
213 final Package owner;
214 final String[] outError;
215 final int nameRes;
216 final int labelRes;
217 final int iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700218 final int logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800219 final int bannerRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700220
221 String tag;
222 TypedArray sa;
223
224 ParsePackageItemArgs(Package _owner, String[] _outError,
Jose Limaf78e3122014-03-06 12:13:15 -0800225 int _nameRes, int _labelRes, int _iconRes, int _logoRes, int _bannerRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700226 owner = _owner;
227 outError = _outError;
228 nameRes = _nameRes;
229 labelRes = _labelRes;
230 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700231 logoRes = _logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800232 bannerRes = _bannerRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700233 }
234 }
235
236 static class ParseComponentArgs extends ParsePackageItemArgs {
237 final String[] sepProcesses;
238 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800239 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700240 final int enabledRes;
241 int flags;
242
243 ParseComponentArgs(Package _owner, String[] _outError,
Jose Limaf78e3122014-03-06 12:13:15 -0800244 int _nameRes, int _labelRes, int _iconRes, int _logoRes, int _bannerRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800245 String[] _sepProcesses, int _processRes,
246 int _descriptionRes, int _enabledRes) {
Jose Limaf78e3122014-03-06 12:13:15 -0800247 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _logoRes, _bannerRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700248 sepProcesses = _sepProcesses;
249 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800250 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700251 enabledRes = _enabledRes;
252 }
253 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800254
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700255 /**
Jeff Sharkey73767b92014-07-04 20:18:13 -0700256 * Lightweight parsed details about a single package.
257 */
258 public static class PackageLite {
259 public final String packageName;
260 public final int versionCode;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700261 public final int installLocation;
262 public final VerifierInfo[] verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700263
264 /** Names of any split APKs, ordered by parsed splitName */
265 public final String[] splitNames;
266
267 /**
268 * Path where this package was found on disk. For monolithic packages
269 * this is path to single base APK file; for cluster packages this is
270 * path to the cluster directory.
271 */
272 public final String codePath;
273
274 /** Path of base APK */
275 public final String baseCodePath;
276 /** Paths of any split APKs, ordered by parsed splitName */
277 public final String[] splitCodePaths;
278
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800279 /** Revision code of base APK */
280 public final int baseRevisionCode;
281 /** Revision codes of any split APKs, ordered by parsed splitName */
282 public final int[] splitRevisionCodes;
283
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700284 public final boolean coreApp;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100285 public final boolean multiArch;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700286 public final boolean extractNativeLibs;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100287
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700288 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800289 String[] splitCodePaths, int[] splitRevisionCodes) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700290 this.packageName = baseApk.packageName;
291 this.versionCode = baseApk.versionCode;
292 this.installLocation = baseApk.installLocation;
293 this.verifiers = baseApk.verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700294 this.splitNames = splitNames;
295 this.codePath = codePath;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700296 this.baseCodePath = baseApk.codePath;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700297 this.splitCodePaths = splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800298 this.baseRevisionCode = baseApk.revisionCode;
299 this.splitRevisionCodes = splitRevisionCodes;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700300 this.coreApp = baseApk.coreApp;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100301 this.multiArch = baseApk.multiArch;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700302 this.extractNativeLibs = baseApk.extractNativeLibs;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700303 }
304
305 public List<String> getAllCodePaths() {
306 ArrayList<String> paths = new ArrayList<>();
307 paths.add(baseCodePath);
308 if (!ArrayUtils.isEmpty(splitCodePaths)) {
309 Collections.addAll(paths, splitCodePaths);
310 }
311 return paths;
312 }
313 }
314
315 /**
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700316 * Lightweight parsed details about a single APK file.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800317 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700318 public static class ApkLite {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700319 public final String codePath;
Kenny Root05ca4c92011-09-15 10:36:25 -0700320 public final String packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700321 public final String splitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700322 public final int versionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800323 public final int revisionCode;
Kenny Root05ca4c92011-09-15 10:36:25 -0700324 public final int installLocation;
325 public final VerifierInfo[] verifiers;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700326 public final Signature[] signatures;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700327 public final boolean coreApp;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100328 public final boolean multiArch;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700329 public final boolean extractNativeLibs;
Kenny Root05ca4c92011-09-15 10:36:25 -0700330
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700331 public ApkLite(String codePath, String packageName, String splitName, int versionCode,
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800332 int revisionCode, int installLocation, List<VerifierInfo> verifiers,
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700333 Signature[] signatures, boolean coreApp, boolean multiArch,
334 boolean extractNativeLibs) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700335 this.codePath = codePath;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800336 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700337 this.splitName = splitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700338 this.versionCode = versionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800339 this.revisionCode = revisionCode;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800340 this.installLocation = installLocation;
Kenny Root05ca4c92011-09-15 10:36:25 -0700341 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700342 this.signatures = signatures;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700343 this.coreApp = coreApp;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100344 this.multiArch = multiArch;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700345 this.extractNativeLibs = extractNativeLibs;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800346 }
347 }
348
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700349 private ParsePackageItemArgs mParseInstrumentationArgs;
350 private ParseComponentArgs mParseActivityArgs;
351 private ParseComponentArgs mParseActivityAliasArgs;
352 private ParseComponentArgs mParseServiceArgs;
353 private ParseComponentArgs mParseProviderArgs;
354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 /** If set to true, we will only allow package files that exactly match
356 * the DTD. Otherwise, we try to get as much from the package as we
357 * can without failing. This should normally be set to false, to
358 * support extensions to the DTD in future versions. */
359 private static final boolean RIGID_PARSER = false;
360
361 private static final String TAG = "PackageParser";
362
Jeff Sharkey275e0852014-06-17 18:18:49 -0700363 public PackageParser() {
364 mMetrics = new DisplayMetrics();
365 mMetrics.setToDefaults();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700366 }
367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 public void setSeparateProcesses(String[] procs) {
369 mSeparateProcesses = procs;
370 }
371
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700372 /**
373 * Flag indicating this parser should only consider apps with
374 * {@code coreApp} manifest attribute to be valid apps. This is useful when
375 * creating a minimalist boot environment.
376 */
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700377 public void setOnlyCoreApps(boolean onlyCoreApps) {
378 mOnlyCoreApps = onlyCoreApps;
379 }
380
Jeff Sharkey275e0852014-06-17 18:18:49 -0700381 public void setDisplayMetrics(DisplayMetrics metrics) {
382 mMetrics = metrics;
383 }
384
Jeff Sharkey73767b92014-07-04 20:18:13 -0700385 public static final boolean isApkFile(File file) {
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700386 return isApkPath(file.getName());
387 }
388
389 private static boolean isApkPath(String path) {
390 return path.endsWith(".apk");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 }
392
393 /**
394 * Generate and return the {@link PackageInfo} for a parsed package.
395 *
396 * @param p the parsed package.
397 * @param flags indicating which optional information is included.
398 */
399 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Dianne Hackborne639da72012-02-21 15:11:13 -0800400 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svet Ganov3695b8a2015-03-24 16:30:25 -0700401 Set<String> grantedPermissions, PackageUserState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402
Amith Yamasani483f3b02012-03-13 16:08:00 -0700403 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700404 grantedPermissions, state, UserHandle.getCallingUserId());
405 }
406
Amith Yamasani655d0e22013-06-12 14:19:10 -0700407 /**
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700408 * Returns true if the package is installed and not hidden, or if the caller
409 * explicitly wanted all uninstalled and hidden packages as well.
Amith Yamasani655d0e22013-06-12 14:19:10 -0700410 */
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700411 private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state) {
412 return (state.installed && !state.hidden)
Amith Yamasani655d0e22013-06-12 14:19:10 -0700413 || (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700414 }
415
Christopher Tateba629da2013-11-13 17:42:28 -0800416 public static boolean isAvailable(PackageUserState state) {
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700417 return checkUseInstalledOrHidden(0, state);
Christopher Tateba629da2013-11-13 17:42:28 -0800418 }
419
Amith Yamasani13593602012-03-22 16:16:17 -0700420 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Amith Yamasani483f3b02012-03-13 16:08:00 -0700421 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svetoslavc6d1c342015-02-26 14:44:43 -0800422 Set<String> grantedPermissions, PackageUserState state, int userId) {
Amith Yamasani742a6712011-05-04 14:49:28 -0700423
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700424 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700425 return null;
426 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800427 PackageInfo pi = new PackageInfo();
428 pi.packageName = p.packageName;
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700429 pi.splitNames = p.splitNames;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430 pi.versionCode = p.mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800431 pi.baseRevisionCode = p.baseRevisionCode;
432 pi.splitRevisionCodes = p.splitRevisionCodes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 pi.versionName = p.mVersionName;
434 pi.sharedUserId = p.mSharedUserId;
435 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700436 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800437 pi.installLocation = p.installLocation;
Jeff Hao272bf3a2014-10-08 13:34:43 -0700438 pi.coreApp = p.coreApp;
Amith Yamasani0d8750d2013-05-01 15:25:28 -0700439 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
440 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
441 pi.requiredForAllUsers = p.mRequiredForAllUsers;
442 }
Amith Yamasani0ac1fc92013-03-27 18:56:08 -0700443 pi.restrictedAccountType = p.mRestrictedAccountType;
Amith Yamasaniccbe3892013-04-12 17:52:42 -0700444 pi.requiredAccountType = p.mRequiredAccountType;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100445 pi.overlayTarget = p.mOverlayTarget;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700446 pi.firstInstallTime = firstInstallTime;
447 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 if ((flags&PackageManager.GET_GIDS) != 0) {
449 pi.gids = gids;
450 }
451 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700452 int N = p.configPreferences != null ? p.configPreferences.size() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453 if (N > 0) {
454 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700455 p.configPreferences.toArray(pi.configPreferences);
456 }
457 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
458 if (N > 0) {
459 pi.reqFeatures = new FeatureInfo[N];
460 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 }
Adam Lesinskid3edfde2014-08-08 17:32:44 -0700462 N = p.featureGroups != null ? p.featureGroups.size() : 0;
463 if (N > 0) {
464 pi.featureGroups = new FeatureGroupInfo[N];
465 p.featureGroups.toArray(pi.featureGroups);
466 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467 }
468 if ((flags&PackageManager.GET_ACTIVITIES) != 0) {
469 int N = p.activities.size();
470 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700471 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
472 pi.activities = new ActivityInfo[N];
473 } else {
474 int num = 0;
475 for (int i=0; i<N; i++) {
476 if (p.activities.get(i).info.enabled) num++;
477 }
478 pi.activities = new ActivityInfo[num];
479 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700480 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 final Activity activity = p.activities.get(i);
482 if (activity.info.enabled
483 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Amith Yamasani742a6712011-05-04 14:49:28 -0700484 pi.activities[j++] = generateActivityInfo(p.activities.get(i), flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700485 state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 }
487 }
488 }
489 }
490 if ((flags&PackageManager.GET_RECEIVERS) != 0) {
491 int N = p.receivers.size();
492 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700493 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
494 pi.receivers = new ActivityInfo[N];
495 } else {
496 int num = 0;
497 for (int i=0; i<N; i++) {
498 if (p.receivers.get(i).info.enabled) num++;
499 }
500 pi.receivers = new ActivityInfo[num];
501 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700502 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 final Activity activity = p.receivers.get(i);
504 if (activity.info.enabled
505 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Amith Yamasani13593602012-03-22 16:16:17 -0700506 pi.receivers[j++] = generateActivityInfo(p.receivers.get(i), flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700507 state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508 }
509 }
510 }
511 }
512 if ((flags&PackageManager.GET_SERVICES) != 0) {
513 int N = p.services.size();
514 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700515 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
516 pi.services = new ServiceInfo[N];
517 } else {
518 int num = 0;
519 for (int i=0; i<N; i++) {
520 if (p.services.get(i).info.enabled) num++;
521 }
522 pi.services = new ServiceInfo[num];
523 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700524 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 final Service service = p.services.get(i);
526 if (service.info.enabled
527 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700528 pi.services[j++] = generateServiceInfo(p.services.get(i), flags,
529 state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530 }
531 }
532 }
533 }
534 if ((flags&PackageManager.GET_PROVIDERS) != 0) {
535 int N = p.providers.size();
536 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700537 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
538 pi.providers = new ProviderInfo[N];
539 } else {
540 int num = 0;
541 for (int i=0; i<N; i++) {
542 if (p.providers.get(i).info.enabled) num++;
543 }
544 pi.providers = new ProviderInfo[num];
545 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700546 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800547 final Provider provider = p.providers.get(i);
548 if (provider.info.enabled
549 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700550 pi.providers[j++] = generateProviderInfo(p.providers.get(i), flags,
551 state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800552 }
553 }
554 }
555 }
556 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
557 int N = p.instrumentation.size();
558 if (N > 0) {
559 pi.instrumentation = new InstrumentationInfo[N];
560 for (int i=0; i<N; i++) {
561 pi.instrumentation[i] = generateInstrumentationInfo(
562 p.instrumentation.get(i), flags);
563 }
564 }
565 }
566 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
567 int N = p.permissions.size();
568 if (N > 0) {
569 pi.permissions = new PermissionInfo[N];
570 for (int i=0; i<N; i++) {
571 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
572 }
573 }
574 N = p.requestedPermissions.size();
575 if (N > 0) {
576 pi.requestedPermissions = new String[N];
Dianne Hackborne639da72012-02-21 15:11:13 -0800577 pi.requestedPermissionsFlags = new int[N];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800578 for (int i=0; i<N; i++) {
Dianne Hackborne639da72012-02-21 15:11:13 -0800579 final String perm = p.requestedPermissions.get(i);
580 pi.requestedPermissions[i] = perm;
Svet Ganov3695b8a2015-03-24 16:30:25 -0700581 // The notion of required permissions is deprecated but for compatibility.
Svetoslavc6d1c342015-02-26 14:44:43 -0800582 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800583 if (grantedPermissions != null && grantedPermissions.contains(perm)) {
584 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
585 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800586 }
587 }
588 }
589 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700590 int N = (p.mSignatures != null) ? p.mSignatures.length : 0;
591 if (N > 0) {
592 pi.signatures = new Signature[N];
593 System.arraycopy(p.mSignatures, 0, pi.signatures, 0, N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 }
595 }
596 return pi;
597 }
598
Jeff Sharkey275e0852014-06-17 18:18:49 -0700599 private static Certificate[][] loadCertificates(StrictJarFile jarFile, ZipEntry entry)
600 throws PackageParserException {
601 InputStream is = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602 try {
603 // We must read the stream for the JarEntry to retrieve
604 // its certificates.
Jeff Sharkey275e0852014-06-17 18:18:49 -0700605 is = jarFile.getInputStream(entry);
606 readFullyIgnoringContents(is);
607 return jarFile.getCertificateChains(entry);
608 } catch (IOException | RuntimeException e) {
609 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
610 "Failed reading " + entry.getName() + " in " + jarFile, e);
611 } finally {
612 IoUtils.closeQuietly(is);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800614 }
615
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800616 public final static int PARSE_IS_SYSTEM = 1<<0;
617 public final static int PARSE_CHATTY = 1<<1;
618 public final static int PARSE_MUST_BE_APK = 1<<2;
619 public final static int PARSE_IGNORE_PROCESSES = 1<<3;
620 public final static int PARSE_FORWARD_LOCK = 1<<4;
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -0700621 public final static int PARSE_EXTERNAL_STORAGE = 1<<5;
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700622 public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
Christopher Tateccbf84f2013-05-08 15:25:41 -0700623 public final static int PARSE_IS_PRIVILEGED = 1<<7;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700624 public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700625 public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
Christopher Tatef3d939c2015-09-17 12:25:51 -0700626 public final static int PARSE_ENFORCE_CODE = 1<<10;
Todd Kennedy27c24fb2015-09-17 16:49:25 -0700627 // TODO: fix b/25118622; remove this entirely once signature processing is quick
628 public final static int PARSE_SKIP_VERIFICATION = 1<<11;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700629
630 private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700632 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700633 * Used to sort a set of APKs based on their split names, always placing the
634 * base APK (with {@code null} split name) first.
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700635 */
Jeff Sharkey275e0852014-06-17 18:18:49 -0700636 private static class SplitNameComparator implements Comparator<String> {
637 @Override
638 public int compare(String lhs, String rhs) {
639 if (lhs == null) {
640 return -1;
641 } else if (rhs == null) {
642 return 1;
643 } else {
644 return lhs.compareTo(rhs);
645 }
646 }
647 }
648
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700649 /**
650 * Parse only lightweight details about the package at the given location.
651 * Automatically detects if the package is a monolithic style (single APK
652 * file) or cluster style (directory of APKs).
653 * <p>
654 * This performs sanity checking on cluster style packages, such as
655 * requiring identical package name and version codes, a single base APK,
656 * and unique split names.
657 *
658 * @see PackageParser#parsePackage(File, int)
659 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700660 public static PackageLite parsePackageLite(File packageFile, int flags)
661 throws PackageParserException {
662 if (packageFile.isDirectory()) {
663 return parseClusterPackageLite(packageFile, flags);
664 } else {
665 return parseMonolithicPackageLite(packageFile, flags);
666 }
667 }
668
669 private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
670 throws PackageParserException {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700671 final ApkLite baseApk = parseApkLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700672 final String packagePath = packageFile.getAbsolutePath();
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800673 return new PackageLite(packagePath, baseApk, null, null, null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700674 }
675
676 private static PackageLite parseClusterPackageLite(File packageDir, int flags)
677 throws PackageParserException {
678 final File[] files = packageDir.listFiles();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700679 if (ArrayUtils.isEmpty(files)) {
680 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
681 "No packages found in split");
682 }
683
Jeff Sharkey275e0852014-06-17 18:18:49 -0700684 String packageName = null;
685 int versionCode = 0;
686
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700687 final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700688 for (File file : files) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700689 if (isApkFile(file)) {
690 final ApkLite lite = parseApkLite(file, flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -0700691
692 // Assert that all package names and version codes are
693 // consistent with the first one we encounter.
694 if (packageName == null) {
695 packageName = lite.packageName;
696 versionCode = lite.versionCode;
697 } else {
698 if (!packageName.equals(lite.packageName)) {
699 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
700 "Inconsistent package " + lite.packageName + " in " + file
701 + "; expected " + packageName);
702 }
703 if (versionCode != lite.versionCode) {
704 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
705 "Inconsistent version " + lite.versionCode + " in " + file
706 + "; expected " + versionCode);
707 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700708 }
709
Jeff Sharkey275e0852014-06-17 18:18:49 -0700710 // Assert that each split is defined only once
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700711 if (apks.put(lite.splitName, lite) != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700712 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
713 "Split name " + lite.splitName
714 + " defined more than once; most recent was " + file);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700715 }
716 }
717 }
718
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700719 final ApkLite baseApk = apks.remove(null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700720 if (baseApk == null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700721 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
Jeff Sharkey73767b92014-07-04 20:18:13 -0700722 "Missing base APK in " + packageDir);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700723 }
724
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700725 // Always apply deterministic ordering based on splitName
726 final int size = apks.size();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700727
Jeff Sharkey73767b92014-07-04 20:18:13 -0700728 String[] splitNames = null;
729 String[] splitCodePaths = null;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800730 int[] splitRevisionCodes = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700731 if (size > 0) {
732 splitNames = new String[size];
733 splitCodePaths = new String[size];
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800734 splitRevisionCodes = new int[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700735
736 splitNames = apks.keySet().toArray(splitNames);
737 Arrays.sort(splitNames, sSplitNameComparator);
738
739 for (int i = 0; i < size; i++) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700740 splitCodePaths[i] = apks.get(splitNames[i]).codePath;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800741 splitRevisionCodes[i] = apks.get(splitNames[i]).revisionCode;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700742 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700743 }
744
Jeff Sharkey73767b92014-07-04 20:18:13 -0700745 final String codePath = packageDir.getAbsolutePath();
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800746 return new PackageLite(codePath, baseApk, splitNames, splitCodePaths,
747 splitRevisionCodes);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700748 }
749
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700750 /**
751 * Parse the package at the given location. Automatically detects if the
752 * package is a monolithic style (single APK file) or cluster style
753 * (directory of APKs).
754 * <p>
755 * This performs sanity checking on cluster style packages, such as
756 * requiring identical package name and version codes, a single base APK,
757 * and unique split names.
758 * <p>
759 * Note that this <em>does not</em> perform signature verification; that
760 * must be done separately in {@link #collectCertificates(Package, int)}.
761 *
762 * @see #parsePackageLite(File, int)
763 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700764 public Package parsePackage(File packageFile, int flags) throws PackageParserException {
765 if (packageFile.isDirectory()) {
766 return parseClusterPackage(packageFile, flags);
767 } else {
768 return parseMonolithicPackage(packageFile, flags);
769 }
770 }
771
772 /**
773 * Parse all APKs contained in the given directory, treating them as a
774 * single package. This also performs sanity checking, such as requiring
775 * identical package name and version codes, a single base APK, and unique
776 * split names.
777 * <p>
778 * Note that this <em>does not</em> perform signature verification; that
779 * must be done separately in {@link #collectCertificates(Package, int)}.
780 */
781 private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
782 final PackageLite lite = parseClusterPackageLite(packageDir, 0);
783
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700784 if (mOnlyCoreApps && !lite.coreApp) {
785 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
786 "Not a coreApp: " + packageDir);
787 }
788
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700789 final AssetManager assets = new AssetManager();
790 try {
791 // Load the base and all splits into the AssetManager
792 // so that resources can be overriden when parsing the manifests.
793 loadApkIntoAssetManager(assets, lite.baseCodePath, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700794
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700795 if (!ArrayUtils.isEmpty(lite.splitCodePaths)) {
796 for (String path : lite.splitCodePaths) {
797 loadApkIntoAssetManager(assets, path, flags);
798 }
Jeff Sharkey73767b92014-07-04 20:18:13 -0700799 }
Jeff Sharkey73767b92014-07-04 20:18:13 -0700800
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700801 final File baseApk = new File(lite.baseCodePath);
802 final Package pkg = parseBaseApk(baseApk, assets, flags);
803 if (pkg == null) {
804 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
805 "Failed to parse base APK: " + baseApk);
806 }
807
808 if (!ArrayUtils.isEmpty(lite.splitNames)) {
809 final int num = lite.splitNames.length;
810 pkg.splitNames = lite.splitNames;
811 pkg.splitCodePaths = lite.splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800812 pkg.splitRevisionCodes = lite.splitRevisionCodes;
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700813 pkg.splitFlags = new int[num];
Alex Klyubinb9f8a522015-02-03 11:12:59 -0800814 pkg.splitPrivateFlags = new int[num];
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700815
816 for (int i = 0; i < num; i++) {
817 parseSplitApk(pkg, i, assets, flags);
818 }
819 }
820
821 pkg.codePath = packageDir.getAbsolutePath();
822 return pkg;
823 } finally {
824 IoUtils.closeQuietly(assets);
825 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 }
827
Jeff Sharkey275e0852014-06-17 18:18:49 -0700828 /**
829 * Parse the given APK file, treating it as as a single monolithic package.
830 * <p>
831 * Note that this <em>does not</em> perform signature verification; that
832 * must be done separately in {@link #collectCertificates(Package, int)}.
Jeff Sharkeyd7460572014-07-06 20:44:55 -0700833 *
834 * @deprecated external callers should move to
835 * {@link #parsePackage(File, int)}. Eventually this method will
836 * be marked private.
Jeff Sharkey275e0852014-06-17 18:18:49 -0700837 */
Jeff Sharkeyd7460572014-07-06 20:44:55 -0700838 @Deprecated
Jeff Sharkey275e0852014-06-17 18:18:49 -0700839 public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700840 if (mOnlyCoreApps) {
841 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
842 if (!lite.coreApp) {
843 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
844 "Not a coreApp: " + apkFile);
845 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700846 }
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700847
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700848 final AssetManager assets = new AssetManager();
849 try {
850 final Package pkg = parseBaseApk(apkFile, assets, flags);
851 pkg.codePath = apkFile.getAbsolutePath();
852 return pkg;
853 } finally {
854 IoUtils.closeQuietly(assets);
855 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700856 }
857
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700858 private static int loadApkIntoAssetManager(AssetManager assets, String apkPath, int flags)
859 throws PackageParserException {
860 if ((flags & PARSE_MUST_BE_APK) != 0 && !isApkPath(apkPath)) {
861 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
862 "Invalid package file: " + apkPath);
863 }
864
865 // The AssetManager guarantees uniqueness for asset paths, so if this asset path
866 // already exists in the AssetManager, addAssetPath will only return the cookie
867 // assigned to it.
868 int cookie = assets.addAssetPath(apkPath);
869 if (cookie == 0) {
870 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
871 "Failed adding asset path: " + apkPath);
872 }
873 return cookie;
874 }
875
876 private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
877 throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700878 final String apkPath = apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -0700879
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700880 String volumeUuid = null;
881 if (apkPath.startsWith(MNT_EXPAND)) {
882 final int end = apkPath.indexOf('/', MNT_EXPAND.length());
883 volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
884 }
885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 mParseError = PackageManager.INSTALL_SUCCEEDED;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700887 mArchiveSourcePath = apkFile.getAbsolutePath();
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700888
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700889 if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700891 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
892
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800893 Resources res = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700894 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800895 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700896 res = new Resources(assets, mMetrics, null);
897 assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
898 Build.VERSION.RESOURCES_SDK_INT);
899 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
900
901 final String[] outError = new String[1];
902 final Package pkg = parseBaseApk(res, parser, flags, outError);
903 if (pkg == null) {
904 throw new PackageParserException(mParseError,
905 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700907
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700908 pkg.volumeUuid = volumeUuid;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700909 pkg.baseCodePath = apkPath;
910 pkg.mSignatures = null;
911
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700912 return pkg;
913
914 } catch (PackageParserException e) {
915 throw e;
916 } catch (Exception e) {
917 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -0700918 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700919 } finally {
920 IoUtils.closeQuietly(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800922 }
923
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700924 private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700925 throws PackageParserException {
926 final String apkPath = pkg.splitCodePaths[splitIndex];
Jeff Sharkey275e0852014-06-17 18:18:49 -0700927
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700928 mParseError = PackageManager.INSTALL_SUCCEEDED;
929 mArchiveSourcePath = apkPath;
930
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700931 if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
932
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700933 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
934
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700935 Resources res = null;
936 XmlResourceParser parser = null;
937 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700938 res = new Resources(assets, mMetrics, null);
939 assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
940 Build.VERSION.RESOURCES_SDK_INT);
941 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
942
943 final String[] outError = new String[1];
944 pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
945 if (pkg == null) {
946 throw new PackageParserException(mParseError,
947 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
948 }
949
950 } catch (PackageParserException e) {
951 throw e;
952 } catch (Exception e) {
953 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -0700954 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700955 } finally {
956 IoUtils.closeQuietly(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700957 }
958 }
959
960 /**
961 * Parse the manifest of a <em>split APK</em>.
962 * <p>
963 * Note that split APKs have many more restrictions on what they're capable
964 * of doing, so many valid features of a base APK have been carefully
965 * omitted here.
966 */
967 private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkey78a13012014-07-15 20:18:34 -0700968 int splitIndex, String[] outError) throws XmlPullParserException, IOException,
969 PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700970 AttributeSet attrs = parser;
971
Jeff Sharkey78a13012014-07-15 20:18:34 -0700972 // We parsed manifest tag earlier; just skip past it
973 parsePackageSplitNames(parser, attrs, flags);
974
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700975 mParseInstrumentationArgs = null;
976 mParseActivityArgs = null;
977 mParseServiceArgs = null;
978 mParseProviderArgs = null;
979
980 int type;
981
982 boolean foundApp = false;
983
984 int outerDepth = parser.getDepth();
985 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
986 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
987 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
988 continue;
989 }
990
991 String tagName = parser.getName();
992 if (tagName.equals("application")) {
993 if (foundApp) {
994 if (RIGID_PARSER) {
995 outError[0] = "<manifest> has more than one <application>";
996 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
997 return null;
998 } else {
999 Slog.w(TAG, "<manifest> has more than one <application>");
1000 XmlUtils.skipCurrentTag(parser);
1001 continue;
1002 }
1003 }
1004
1005 foundApp = true;
1006 if (!parseSplitApplication(pkg, res, parser, attrs, flags, splitIndex, outError)) {
1007 return null;
1008 }
1009
1010 } else if (RIGID_PARSER) {
1011 outError[0] = "Bad element under <manifest>: "
1012 + parser.getName();
1013 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1014 return null;
1015
1016 } else {
1017 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1018 + " at " + mArchiveSourcePath + " "
1019 + parser.getPositionDescription());
1020 XmlUtils.skipCurrentTag(parser);
1021 continue;
1022 }
1023 }
1024
1025 if (!foundApp) {
1026 outError[0] = "<manifest> does not contain an <application>";
1027 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1028 }
1029
1030 return pkg;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001031 }
1032
Kenny Root6c918ce2013-04-02 14:04:24 -07001033 /**
1034 * Gathers the {@link ManifestDigest} for {@code pkg} if it exists in the
1035 * APK. If it successfully scanned the package and found the
1036 * {@code AndroidManifest.xml}, {@code true} is returned.
1037 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001038 public void collectManifestDigest(Package pkg) throws PackageParserException {
Jeff Sharkey032f2b22014-06-19 15:48:47 -07001039 pkg.manifestDigest = null;
1040
Jeff Sharkey275e0852014-06-17 18:18:49 -07001041 // TODO: extend to gather digest for split APKs
Kenny Root6c918ce2013-04-02 14:04:24 -07001042 try {
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07001043 final StrictJarFile jarFile = new StrictJarFile(pkg.baseCodePath);
Kenny Root6c918ce2013-04-02 14:04:24 -07001044 try {
Narayan Kamatheb565dc2013-12-12 16:54:33 +00001045 final ZipEntry je = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
Kenny Root6c918ce2013-04-02 14:04:24 -07001046 if (je != null) {
1047 pkg.manifestDigest = ManifestDigest.fromInputStream(jarFile.getInputStream(je));
1048 }
1049 } finally {
1050 jarFile.close();
1051 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001052 } catch (IOException | RuntimeException e) {
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001053 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1054 "Failed to collect manifest digest");
Kenny Root6c918ce2013-04-02 14:04:24 -07001055 }
1056 }
1057
Jeff Sharkey275e0852014-06-17 18:18:49 -07001058 /**
1059 * Collect certificates from all the APKs described in the given package,
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001060 * populating {@link Package#mSignatures}.
1061 * <p>Depending upon the parser flags, this may also asserts that all APK
Jeff Sharkey275e0852014-06-17 18:18:49 -07001062 * contents are signed correctly and consistently.
1063 */
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001064 public void collectCertificates(Package pkg, int parseFlags) throws PackageParserException {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001065 pkg.mCertificates = null;
1066 pkg.mSignatures = null;
1067 pkg.mSigningKeys = null;
1068
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001069 collectCertificates(pkg, new File(pkg.baseCodePath), parseFlags);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001070
1071 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
1072 for (String splitCodePath : pkg.splitCodePaths) {
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001073 collectCertificates(pkg, new File(splitCodePath), parseFlags);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001074 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001075 }
1076 }
1077
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001078 private static void collectCertificates(Package pkg, File apkFile, int parseFlags)
Jeff Sharkey275e0852014-06-17 18:18:49 -07001079 throws PackageParserException {
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001080 final boolean requireCode = ((parseFlags & PARSE_ENFORCE_CODE) != 0)
Christopher Tatef3d939c2015-09-17 12:25:51 -07001081 && ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001082 final String apkPath = apkFile.getAbsolutePath();
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001083 final boolean skipVerification = Build.IS_DEBUGGABLE
1084 && ((parseFlags & PARSE_SKIP_VERIFICATION) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001085
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001086 boolean codeFound = skipVerification;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001087 StrictJarFile jarFile = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 try {
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001089 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor");
Jeff Sharkey275e0852014-06-17 18:18:49 -07001090 jarFile = new StrictJarFile(apkPath);
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001091 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092
Jeff Sharkey275e0852014-06-17 18:18:49 -07001093 // Always verify manifest, regardless of source
1094 final ZipEntry manifestEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
1095 if (manifestEntry == null) {
1096 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1097 "Package " + apkPath + " has no manifest");
1098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001100 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "buildVerifyList");
Jeff Sharkey275e0852014-06-17 18:18:49 -07001101 final List<ZipEntry> toVerify = new ArrayList<>();
1102 toVerify.add(manifestEntry);
1103
1104 // If we're parsing an untrusted package, verify all contents
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001105 if (!skipVerification && (parseFlags & PARSE_IS_SYSTEM) == 0) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001106 final Iterator<ZipEntry> i = jarFile.iterator();
1107 while (i.hasNext()) {
1108 final ZipEntry entry = i.next();
1109
1110 if (entry.isDirectory()) continue;
Christopher Tatef3d939c2015-09-17 12:25:51 -07001111
1112 final String entryName = entry.getName();
1113 if (entryName.startsWith("META-INF/")) continue;
1114 if (entryName.equals(ANDROID_MANIFEST_FILENAME)) continue;
1115 if (entryName.equals(BYTECODE_FILENAME)) {
1116 codeFound = true;
1117 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001118
1119 toVerify.add(entry);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001121 }
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001122 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001123
Christopher Tatef3d939c2015-09-17 12:25:51 -07001124 if (!codeFound && requireCode) {
1125 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1126 "Package " + apkPath + " code is missing");
1127 }
1128
Jeff Sharkey275e0852014-06-17 18:18:49 -07001129 // Verify that entries are signed consistently with the first entry
1130 // we encountered. Note that for splits, certificates may have
1131 // already been populated during an earlier parse of a base APK.
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001132 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyEntries");
Jeff Sharkey275e0852014-06-17 18:18:49 -07001133 for (ZipEntry entry : toVerify) {
1134 final Certificate[][] entryCerts = loadCertificates(jarFile, entry);
1135 if (ArrayUtils.isEmpty(entryCerts)) {
1136 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1137 "Package " + apkPath + " has no certificates at entry "
1138 + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001139 }
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001140 final Signature[] entrySignatures = convertToSignatures(entryCerts);
Kenny Rootd2d29252011-08-08 11:27:57 -07001141
Jeff Sharkey275e0852014-06-17 18:18:49 -07001142 if (pkg.mCertificates == null) {
1143 pkg.mCertificates = entryCerts;
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001144 pkg.mSignatures = entrySignatures;
dcashman55b10782014-04-09 14:20:38 -07001145 pkg.mSigningKeys = new ArraySet<PublicKey>();
1146 for (int i=0; i < entryCerts.length; i++) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001147 pkg.mSigningKeys.add(entryCerts[i][0].getPublicKey());
Kenny Rootbcc954d2011-08-08 16:19:08 -07001148 }
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001149 if (skipVerification) {
1150 break;
1151 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001152 } else {
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001153 if (!Signature.areExactMatch(pkg.mSignatures, entrySignatures)) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001154 throw new PackageParserException(
1155 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, "Package " + apkPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 + " has mismatched certificates at entry "
Jeff Sharkey275e0852014-06-17 18:18:49 -07001157 + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001158 }
1159 }
1160 }
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001161 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeybc097552014-09-09 14:57:26 -07001162 } catch (GeneralSecurityException e) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001163 throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING,
1164 "Failed to collect certificates from " + apkPath, e);
Jeff Sharkeybc097552014-09-09 14:57:26 -07001165 } catch (IOException | RuntimeException e) {
1166 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1167 "Failed to collect certificates from " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001168 } finally {
1169 closeQuietly(jarFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001170 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001171 }
1172
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001173 private static Signature[] convertToSignatures(Certificate[][] certs)
1174 throws CertificateEncodingException {
1175 final Signature[] res = new Signature[certs.length];
1176 for (int i = 0; i < certs.length; i++) {
1177 res[i] = new Signature(certs[i]);
1178 }
1179 return res;
1180 }
1181
Jeff Sharkey275e0852014-06-17 18:18:49 -07001182 /**
1183 * Utility method that retrieves lightweight details about a single APK
1184 * file, including package name, split name, and install location.
1185 *
1186 * @param apkFile path to a single APK
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001187 * @param flags optional parse flags, such as
1188 * {@link #PARSE_COLLECT_CERTIFICATES}
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001189 */
Jeff Sharkey275e0852014-06-17 18:18:49 -07001190 public static ApkLite parseApkLite(File apkFile, int flags)
1191 throws PackageParserException {
1192 final String apkPath = apkFile.getAbsolutePath();
1193
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001194 AssetManager assets = null;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001195 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001196 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001197 assets = new AssetManager();
1198 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 -08001199 Build.VERSION.RESOURCES_SDK_INT);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001200
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001201 int cookie = assets.addAssetPath(apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001202 if (cookie == 0) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001203 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1204 "Failed to parse " + apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001205 }
1206
Kenny Root05ca4c92011-09-15 10:36:25 -07001207 final DisplayMetrics metrics = new DisplayMetrics();
1208 metrics.setToDefaults();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001209
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001210 final Resources res = new Resources(assets, metrics, null);
1211 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Kenny Root05ca4c92011-09-15 10:36:25 -07001212
Jeff Sharkey275e0852014-06-17 18:18:49 -07001213 final Signature[] signatures;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001214 if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
1215 // TODO: factor signature related items out of Package object
1216 final Package tempPkg = new Package(null);
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001217 // TODO: fix b/25118622; pass in '0' for parse flags
1218 collectCertificates(tempPkg, apkFile, flags & PARSE_SKIP_VERIFICATION);
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001219 signatures = tempPkg.mSignatures;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001220 } else {
1221 signatures = null;
1222 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001223
Jeff Sharkey275e0852014-06-17 18:18:49 -07001224 final AttributeSet attrs = parser;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -07001225 return parseApkLite(apkPath, res, parser, attrs, flags, signatures);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001226
1227 } catch (XmlPullParserException | IOException | RuntimeException e) {
1228 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1229 "Failed to parse " + apkPath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001230 } finally {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001231 IoUtils.closeQuietly(parser);
1232 IoUtils.closeQuietly(assets);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001233 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001234 }
1235
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001236 private static String validateName(String name, boolean requireSeparator,
1237 boolean requireFilename) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 final int N = name.length();
1239 boolean hasSep = false;
1240 boolean front = true;
1241 for (int i=0; i<N; i++) {
1242 final char c = name.charAt(i);
1243 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1244 front = false;
1245 continue;
1246 }
1247 if (!front) {
1248 if ((c >= '0' && c <= '9') || c == '_') {
1249 continue;
1250 }
1251 }
1252 if (c == '.') {
1253 hasSep = true;
1254 front = true;
1255 continue;
1256 }
1257 return "bad character '" + c + "'";
1258 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001259 if (requireFilename && !FileUtils.isValidExtFilename(name)) {
1260 return "Invalid filename";
1261 }
1262 return hasSep || !requireSeparator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001263 ? null : "must have at least one '.' separator";
1264 }
1265
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001266 private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
1267 AttributeSet attrs, int flags) throws IOException, XmlPullParserException,
1268 PackageParserException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001269
1270 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001271 while ((type = parser.next()) != XmlPullParser.START_TAG
1272 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001273 }
1274
Kenny Rootd2d29252011-08-08 11:27:57 -07001275 if (type != XmlPullParser.START_TAG) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001276 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1277 "No start tag found");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001279 if (!parser.getName().equals("manifest")) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001280 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1281 "No <manifest> tag");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001282 }
1283
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001284 final String packageName = attrs.getAttributeValue(null, "package");
1285 if (!"android".equals(packageName)) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001286 final String error = validateName(packageName, true, true);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001287 if (error != null) {
1288 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1289 "Invalid manifest package: " + error);
1290 }
1291 }
1292
Jeff Sharkey275e0852014-06-17 18:18:49 -07001293 String splitName = attrs.getAttributeValue(null, "split");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001294 if (splitName != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001295 if (splitName.length() == 0) {
1296 splitName = null;
1297 } else {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001298 final String error = validateName(splitName, false, false);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001299 if (error != null) {
1300 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1301 "Invalid manifest split: " + error);
1302 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001303 }
1304 }
1305
1306 return Pair.create(packageName.intern(),
1307 (splitName != null) ? splitName.intern() : splitName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001308 }
1309
Jeff Sharkeybe520fb2014-07-04 18:23:17 -07001310 private static ApkLite parseApkLite(String codePath, Resources res, XmlPullParser parser,
Jeff Sharkey275e0852014-06-17 18:18:49 -07001311 AttributeSet attrs, int flags, Signature[] signatures) throws IOException,
1312 XmlPullParserException, PackageParserException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001313 final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs, flags);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001314
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001315 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001316 int versionCode = 0;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001317 int revisionCode = 0;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001318 boolean coreApp = false;
Narayan Kamathff110bd2014-07-04 18:30:45 +01001319 boolean multiArch = false;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001320 boolean extractNativeLibs = true;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001321
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001322 for (int i = 0; i < attrs.getAttributeCount(); i++) {
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001323 final String attr = attrs.getAttributeName(i);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001324 if (attr.equals("installLocation")) {
1325 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001326 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001327 } else if (attr.equals("versionCode")) {
1328 versionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001329 } else if (attr.equals("revisionCode")) {
1330 revisionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001331 } else if (attr.equals("coreApp")) {
1332 coreApp = attrs.getAttributeBooleanValue(i, false);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001333 }
1334 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001335
1336 // Only search the tree when the tag is directly below <manifest>
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001337 int type;
Kenny Root05ca4c92011-09-15 10:36:25 -07001338 final int searchDepth = parser.getDepth() + 1;
1339
1340 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
1341 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1342 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
1343 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1344 continue;
1345 }
1346
1347 if (parser.getDepth() == searchDepth && "package-verifier".equals(parser.getName())) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001348 final VerifierInfo verifier = parseVerifier(res, parser, attrs, flags);
Kenny Root05ca4c92011-09-15 10:36:25 -07001349 if (verifier != null) {
1350 verifiers.add(verifier);
1351 }
1352 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001353
1354 if (parser.getDepth() == searchDepth && "application".equals(parser.getName())) {
1355 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1356 final String attr = attrs.getAttributeName(i);
1357 if ("multiArch".equals(attr)) {
1358 multiArch = attrs.getAttributeBooleanValue(i, false);
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001359 }
1360 if ("extractNativeLibs".equals(attr)) {
1361 extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
Narayan Kamatha8755a82014-07-15 12:26:35 +01001362 }
1363 }
1364 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001365 }
1366
Jeff Sharkeybe520fb2014-07-04 18:23:17 -07001367 return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode,
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001368 revisionCode, installLocation, verifiers, signatures, coreApp, multiArch,
1369 extractNativeLibs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001370 }
1371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 /**
1373 * Temporary.
1374 */
1375 static public Signature stringToSignature(String str) {
1376 final int N = str.length();
1377 byte[] sig = new byte[N];
1378 for (int i=0; i<N; i++) {
1379 sig[i] = (byte)str.charAt(i);
1380 }
1381 return new Signature(sig);
1382 }
1383
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001384 /**
1385 * Parse the manifest of a <em>base APK</em>.
1386 * <p>
1387 * When adding new features, carefully consider if they should also be
1388 * supported by split APKs.
1389 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001390 private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001391 String[] outError) throws XmlPullParserException, IOException {
1392 final boolean trustedOverlay = (flags & PARSE_TRUSTED_OVERLAY) != 0;
1393
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001394 AttributeSet attrs = parser;
1395
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001396 mParseInstrumentationArgs = null;
1397 mParseActivityArgs = null;
1398 mParseServiceArgs = null;
1399 mParseProviderArgs = null;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001400
1401 final String pkgName;
1402 final String splitName;
1403 try {
1404 Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs, flags);
1405 pkgName = packageSplit.first;
1406 splitName = packageSplit.second;
1407 } catch (PackageParserException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1409 return null;
1410 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001412 int type;
1413
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001414 if (!TextUtils.isEmpty(splitName)) {
1415 outError[0] = "Expected base APK, but found split " + splitName;
1416 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1417 return null;
1418 }
1419
1420 final Package pkg = new Package(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001421 boolean foundApp = false;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001422
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 TypedArray sa = res.obtainAttributes(attrs,
1424 com.android.internal.R.styleable.AndroidManifest);
Dianne Hackborn8472e612014-01-23 17:57:20 -08001425 pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001426 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001427 pkg.baseRevisionCode = sa.getInteger(
1428 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001429 pkg.mVersionName = sa.getNonConfigurationString(
1430 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001431 if (pkg.mVersionName != null) {
1432 pkg.mVersionName = pkg.mVersionName.intern();
1433 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001434 String str = sa.getNonConfigurationString(
1435 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
1436 if (str != null && str.length() > 0) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001437 String nameError = validateName(str, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438 if (nameError != null && !"android".equals(pkgName)) {
1439 outError[0] = "<manifest> specifies bad sharedUserId name \""
1440 + str + "\": " + nameError;
1441 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
1442 return null;
1443 }
1444 pkg.mSharedUserId = str.intern();
1445 pkg.mSharedUserLabel = sa.getResourceId(
1446 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
1447 }
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -08001448
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08001449 pkg.installLocation = sa.getInteger(
1450 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001451 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -07001452 pkg.applicationInfo.installLocation = pkg.installLocation;
Kenny Root7cb9be22012-05-30 15:30:37 -07001453
Jeff Hao272bf3a2014-10-08 13:34:43 -07001454 pkg.coreApp = attrs.getAttributeBooleanValue(null, "coreApp", false);
1455
Alan Viverettefd274a02014-03-27 15:39:15 -07001456 sa.recycle();
1457
Kenny Root7cb9be22012-05-30 15:30:37 -07001458 /* Set the global "forward lock" flag */
1459 if ((flags & PARSE_FORWARD_LOCK) != 0) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08001460 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
Kenny Root7cb9be22012-05-30 15:30:37 -07001461 }
1462
1463 /* Set the global "on SD card" flag */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001464 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
Kenny Root7cb9be22012-05-30 15:30:37 -07001465 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
1466 }
1467
Dianne Hackborn723738c2009-06-25 19:48:04 -07001468 // Resource boolean are -1, so 1 means we don't know the value.
1469 int supportsSmallScreens = 1;
1470 int supportsNormalScreens = 1;
1471 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001472 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001473 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001474 int anyDensity = 1;
Dianne Hackborn723738c2009-06-25 19:48:04 -07001475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001476 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -07001477 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1478 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1479 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480 continue;
1481 }
1482
1483 String tagName = parser.getName();
1484 if (tagName.equals("application")) {
1485 if (foundApp) {
1486 if (RIGID_PARSER) {
1487 outError[0] = "<manifest> has more than one <application>";
1488 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1489 return null;
1490 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07001491 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 XmlUtils.skipCurrentTag(parser);
1493 continue;
1494 }
1495 }
1496
1497 foundApp = true;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001498 if (!parseBaseApplication(pkg, res, parser, attrs, flags, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 return null;
1500 }
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01001501 } else if (tagName.equals("overlay")) {
1502 pkg.mTrustedOverlay = trustedOverlay;
1503
1504 sa = res.obtainAttributes(attrs,
1505 com.android.internal.R.styleable.AndroidManifestResourceOverlay);
1506 pkg.mOverlayTarget = sa.getString(
1507 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
1508 pkg.mOverlayPriority = sa.getInt(
1509 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
1510 -1);
1511 sa.recycle();
1512
1513 if (pkg.mOverlayTarget == null) {
1514 outError[0] = "<overlay> does not specify a target package";
1515 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1516 return null;
1517 }
1518 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
1519 outError[0] = "<overlay> priority must be between 0 and 9999";
1520 mParseError =
1521 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1522 return null;
1523 }
1524 XmlUtils.skipCurrentTag(parser);
1525
dcashman989eb3712014-06-17 12:56:12 -07001526 } else if (tagName.equals("key-sets")) {
1527 if (!parseKeySets(pkg, res, parser, attrs, outError)) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08001528 return null;
1529 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 } else if (tagName.equals("permission-group")) {
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07001531 if (parsePermissionGroup(pkg, flags, res, parser, attrs, outError) == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 return null;
1533 }
1534 } else if (tagName.equals("permission")) {
1535 if (parsePermission(pkg, res, parser, attrs, outError) == null) {
1536 return null;
1537 }
1538 } else if (tagName.equals("permission-tree")) {
1539 if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
1540 return null;
1541 }
1542 } else if (tagName.equals("uses-permission")) {
Svetoslav96a77162015-04-03 13:58:33 -07001543 if (!parseUsesPermission(pkg, res, parser, attrs)) {
1544 return null;
1545 }
Svet Ganovffd25bb2015-06-29 18:27:20 -07001546 } else if (tagName.equals("uses-permission-sdk-m")
1547 || tagName.equals("uses-permission-sdk-23")) {
Svetoslav96a77162015-04-03 13:58:33 -07001548 if (!parseUsesPermission(pkg, res, parser, attrs)) {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07001549 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001551 } else if (tagName.equals("uses-configuration")) {
1552 ConfigurationInfo cPref = new ConfigurationInfo();
1553 sa = res.obtainAttributes(attrs,
1554 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
1555 cPref.reqTouchScreen = sa.getInt(
1556 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
1557 Configuration.TOUCHSCREEN_UNDEFINED);
1558 cPref.reqKeyboardType = sa.getInt(
1559 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
1560 Configuration.KEYBOARD_UNDEFINED);
1561 if (sa.getBoolean(
1562 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
1563 false)) {
1564 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
1565 }
1566 cPref.reqNavigation = sa.getInt(
1567 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
1568 Configuration.NAVIGATION_UNDEFINED);
1569 if (sa.getBoolean(
1570 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
1571 false)) {
1572 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
1573 }
1574 sa.recycle();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001575 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001576
1577 XmlUtils.skipCurrentTag(parser);
1578
Suchi Amalapurapud299b812009-06-05 10:26:19 -07001579 } else if (tagName.equals("uses-feature")) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07001580 FeatureInfo fi = parseUsesFeature(res, attrs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001581 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
1582
Dianne Hackborn49237342009-08-27 20:08:01 -07001583 if (fi.name == null) {
1584 ConfigurationInfo cPref = new ConfigurationInfo();
1585 cPref.reqGlEsVersion = fi.reqGlEsVersion;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001586 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
Dianne Hackborn49237342009-08-27 20:08:01 -07001587 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07001588
1589 XmlUtils.skipCurrentTag(parser);
1590
Adam Lesinski2c72b682014-06-24 09:56:01 -07001591 } else if (tagName.equals("feature-group")) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07001592 FeatureGroupInfo group = new FeatureGroupInfo();
1593 ArrayList<FeatureInfo> features = null;
1594 final int innerDepth = parser.getDepth();
1595 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1596 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
1597 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1598 continue;
1599 }
Adam Lesinski2c72b682014-06-24 09:56:01 -07001600
Adam Lesinskid3edfde2014-08-08 17:32:44 -07001601 final String innerTagName = parser.getName();
1602 if (innerTagName.equals("uses-feature")) {
1603 FeatureInfo featureInfo = parseUsesFeature(res, attrs);
1604 // FeatureGroups are stricter and mandate that
1605 // any <uses-feature> declared are mandatory.
1606 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
1607 features = ArrayUtils.add(features, featureInfo);
1608 } else {
1609 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
1610 " at " + mArchiveSourcePath + " " +
1611 parser.getPositionDescription());
1612 }
1613 XmlUtils.skipCurrentTag(parser);
1614 }
1615
1616 if (features != null) {
1617 group.features = new FeatureInfo[features.size()];
1618 group.features = features.toArray(group.features);
1619 }
1620 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
Adam Lesinski2c72b682014-06-24 09:56:01 -07001621
Dianne Hackborn851a5412009-05-08 12:06:44 -07001622 } else if (tagName.equals("uses-sdk")) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001623 if (SDK_VERSION > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 sa = res.obtainAttributes(attrs,
1625 com.android.internal.R.styleable.AndroidManifestUsesSdk);
1626
Dianne Hackborn851a5412009-05-08 12:06:44 -07001627 int minVers = 0;
1628 String minCode = null;
1629 int targetVers = 0;
1630 String targetCode = null;
1631
1632 TypedValue val = sa.peekValue(
1633 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
1634 if (val != null) {
1635 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
1636 targetCode = minCode = val.string.toString();
1637 } else {
1638 // If it's not a string, it's an integer.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001639 targetVers = minVers = val.data;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001640 }
1641 }
1642
1643 val = sa.peekValue(
1644 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
1645 if (val != null) {
1646 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
1647 targetCode = minCode = val.string.toString();
1648 } else {
1649 // If it's not a string, it's an integer.
1650 targetVers = val.data;
1651 }
1652 }
1653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001654 sa.recycle();
1655
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001656 if (minCode != null) {
Dianne Hackbornffcda102014-04-24 13:06:27 -07001657 boolean allowedCodename = false;
1658 for (String codename : SDK_CODENAMES) {
1659 if (minCode.equals(codename)) {
1660 allowedCodename = true;
1661 break;
1662 }
1663 }
1664 if (!allowedCodename) {
1665 if (SDK_CODENAMES.length > 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001666 outError[0] = "Requires development platform " + minCode
Dianne Hackbornffcda102014-04-24 13:06:27 -07001667 + " (current platform is any of "
1668 + Arrays.toString(SDK_CODENAMES) + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001669 } else {
1670 outError[0] = "Requires development platform " + minCode
1671 + " but this is a release platform.";
1672 }
1673 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1674 return null;
1675 }
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001676 } else if (minVers > SDK_VERSION) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001677 outError[0] = "Requires newer sdk version #" + minVers
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001678 + " (current version is #" + SDK_VERSION + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001679 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1680 return null;
1681 }
1682
Dianne Hackborn851a5412009-05-08 12:06:44 -07001683 if (targetCode != null) {
Dianne Hackbornffcda102014-04-24 13:06:27 -07001684 boolean allowedCodename = false;
1685 for (String codename : SDK_CODENAMES) {
1686 if (targetCode.equals(codename)) {
1687 allowedCodename = true;
1688 break;
1689 }
1690 }
1691 if (!allowedCodename) {
1692 if (SDK_CODENAMES.length > 0) {
Dianne Hackborn851a5412009-05-08 12:06:44 -07001693 outError[0] = "Requires development platform " + targetCode
Dianne Hackbornffcda102014-04-24 13:06:27 -07001694 + " (current platform is any of "
1695 + Arrays.toString(SDK_CODENAMES) + ")";
Dianne Hackborn851a5412009-05-08 12:06:44 -07001696 } else {
1697 outError[0] = "Requires development platform " + targetCode
1698 + " but this is a release platform.";
1699 }
1700 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1701 return null;
1702 }
1703 // If the code matches, it definitely targets this SDK.
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001704 pkg.applicationInfo.targetSdkVersion
1705 = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
1706 } else {
1707 pkg.applicationInfo.targetSdkVersion = targetVers;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001708 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 }
1710
1711 XmlUtils.skipCurrentTag(parser);
1712
Dianne Hackborn723738c2009-06-25 19:48:04 -07001713 } else if (tagName.equals("supports-screens")) {
1714 sa = res.obtainAttributes(attrs,
1715 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
1716
Dianne Hackborndf6e9802011-05-26 14:20:23 -07001717 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
1718 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
1719 0);
1720 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
1721 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
1722 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07001723 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
1724 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
1725 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07001726
Dianne Hackborn723738c2009-06-25 19:48:04 -07001727 // This is a trick to get a boolean and still able to detect
1728 // if a value was actually set.
1729 supportsSmallScreens = sa.getInteger(
1730 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
1731 supportsSmallScreens);
1732 supportsNormalScreens = sa.getInteger(
1733 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
1734 supportsNormalScreens);
1735 supportsLargeScreens = sa.getInteger(
1736 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
1737 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001738 supportsXLargeScreens = sa.getInteger(
1739 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
1740 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001741 resizeable = sa.getInteger(
1742 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001743 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001744 anyDensity = sa.getInteger(
1745 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
1746 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07001747
1748 sa.recycle();
1749
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07001750 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn854060af2009-07-09 18:14:31 -07001751
1752 } else if (tagName.equals("protected-broadcast")) {
1753 sa = res.obtainAttributes(attrs,
1754 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
1755
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001756 // Note: don't allow this value to be a reference to a resource
1757 // that may change.
Dianne Hackborn854060af2009-07-09 18:14:31 -07001758 String name = sa.getNonResourceString(
1759 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
1760
1761 sa.recycle();
1762
1763 if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
1764 if (pkg.protectedBroadcasts == null) {
1765 pkg.protectedBroadcasts = new ArrayList<String>();
1766 }
1767 if (!pkg.protectedBroadcasts.contains(name)) {
1768 pkg.protectedBroadcasts.add(name.intern());
1769 }
1770 }
1771
1772 XmlUtils.skipCurrentTag(parser);
1773
1774 } else if (tagName.equals("instrumentation")) {
1775 if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) {
1776 return null;
1777 }
1778
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001779 } else if (tagName.equals("original-package")) {
1780 sa = res.obtainAttributes(attrs,
1781 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
1782
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001783 String orig =sa.getNonConfigurationString(
1784 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001785 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08001786 if (pkg.mOriginalPackages == null) {
1787 pkg.mOriginalPackages = new ArrayList<String>();
1788 pkg.mRealPackage = pkg.packageName;
1789 }
1790 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001791 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001792
1793 sa.recycle();
1794
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001795 XmlUtils.skipCurrentTag(parser);
1796
1797 } else if (tagName.equals("adopt-permissions")) {
1798 sa = res.obtainAttributes(attrs,
1799 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
1800
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001801 String name = sa.getNonConfigurationString(
1802 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001803
1804 sa.recycle();
1805
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001806 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001807 if (pkg.mAdoptPermissions == null) {
1808 pkg.mAdoptPermissions = new ArrayList<String>();
1809 }
1810 pkg.mAdoptPermissions.add(name);
1811 }
1812
1813 XmlUtils.skipCurrentTag(parser);
1814
Dianne Hackborna0b46c92010-10-21 15:32:06 -07001815 } else if (tagName.equals("uses-gl-texture")) {
1816 // Just skip this tag
1817 XmlUtils.skipCurrentTag(parser);
1818 continue;
1819
1820 } else if (tagName.equals("compatible-screens")) {
1821 // Just skip this tag
1822 XmlUtils.skipCurrentTag(parser);
1823 continue;
Michael Wrighteaeb1902013-09-05 18:15:57 -07001824 } else if (tagName.equals("supports-input")) {
1825 XmlUtils.skipCurrentTag(parser);
1826 continue;
Dianne Hackborna0b46c92010-10-21 15:32:06 -07001827
Dianne Hackborn854060af2009-07-09 18:14:31 -07001828 } else if (tagName.equals("eat-comment")) {
1829 // Just skip this tag
1830 XmlUtils.skipCurrentTag(parser);
1831 continue;
1832
1833 } else if (RIGID_PARSER) {
1834 outError[0] = "Bad element under <manifest>: "
1835 + parser.getName();
1836 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1837 return null;
1838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07001840 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07001841 + " at " + mArchiveSourcePath + " "
1842 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001843 XmlUtils.skipCurrentTag(parser);
1844 continue;
1845 }
1846 }
1847
1848 if (!foundApp && pkg.instrumentation.size() == 0) {
1849 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
1850 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1851 }
1852
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001853 final int NP = PackageParser.NEW_PERMISSIONS.length;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001854 StringBuilder implicitPerms = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001855 for (int ip=0; ip<NP; ip++) {
1856 final PackageParser.NewPermissionInfo npi
1857 = PackageParser.NEW_PERMISSIONS[ip];
1858 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
1859 break;
1860 }
1861 if (!pkg.requestedPermissions.contains(npi.name)) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001862 if (implicitPerms == null) {
1863 implicitPerms = new StringBuilder(128);
1864 implicitPerms.append(pkg.packageName);
1865 implicitPerms.append(": compat added ");
1866 } else {
1867 implicitPerms.append(' ');
1868 }
1869 implicitPerms.append(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001870 pkg.requestedPermissions.add(npi.name);
1871 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07001872 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001873 if (implicitPerms != null) {
Kenny Rootd2d29252011-08-08 11:27:57 -07001874 Slog.i(TAG, implicitPerms.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001875 }
Dianne Hackborn79245122012-03-12 10:51:26 -07001876
1877 final int NS = PackageParser.SPLIT_PERMISSIONS.length;
1878 for (int is=0; is<NS; is++) {
1879 final PackageParser.SplitPermissionInfo spi
1880 = PackageParser.SPLIT_PERMISSIONS[is];
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -07001881 if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
1882 || !pkg.requestedPermissions.contains(spi.rootPerm)) {
Dianne Hackborn5e4705a2012-04-06 12:55:53 -07001883 continue;
Dianne Hackborn79245122012-03-12 10:51:26 -07001884 }
1885 for (int in=0; in<spi.newPerms.length; in++) {
1886 final String perm = spi.newPerms[in];
1887 if (!pkg.requestedPermissions.contains(perm)) {
1888 pkg.requestedPermissions.add(perm);
Dianne Hackborn79245122012-03-12 10:51:26 -07001889 }
1890 }
1891 }
1892
Dianne Hackborn723738c2009-06-25 19:48:04 -07001893 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
1894 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001895 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001896 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
1897 }
1898 if (supportsNormalScreens != 0) {
1899 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
1900 }
1901 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
1902 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001903 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001904 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
1905 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001906 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
1907 && pkg.applicationInfo.targetSdkVersion
1908 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
1909 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
1910 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001911 if (resizeable < 0 || (resizeable > 0
1912 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001913 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001914 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
1915 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001916 if (anyDensity < 0 || (anyDensity > 0
1917 && pkg.applicationInfo.targetSdkVersion
1918 >= android.os.Build.VERSION_CODES.DONUT)) {
1919 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07001920 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07001921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001922 return pkg;
1923 }
1924
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001925 private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07001926 FeatureInfo fi = new FeatureInfo();
1927 TypedArray sa = res.obtainAttributes(attrs,
1928 com.android.internal.R.styleable.AndroidManifestUsesFeature);
1929 // Note: don't allow this value to be a reference to a resource
1930 // that may change.
1931 fi.name = sa.getNonResourceString(
1932 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
1933 if (fi.name == null) {
1934 fi.reqGlEsVersion = sa.getInt(
1935 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
1936 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1937 }
1938 if (sa.getBoolean(
1939 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) {
1940 fi.flags |= FeatureInfo.FLAG_REQUIRED;
1941 }
1942 sa.recycle();
1943 return fi;
1944 }
1945
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07001946 private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser,
Svetoslav96a77162015-04-03 13:58:33 -07001947 AttributeSet attrs) throws XmlPullParserException, IOException {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07001948 TypedArray sa = res.obtainAttributes(attrs,
1949 com.android.internal.R.styleable.AndroidManifestUsesPermission);
1950
1951 // Note: don't allow this value to be a reference to a resource
1952 // that may change.
1953 String name = sa.getNonResourceString(
1954 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07001955
Christopher Tatefb0676a2013-09-16 16:34:52 -07001956 int maxSdkVersion = 0;
1957 TypedValue val = sa.peekValue(
1958 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
1959 if (val != null) {
1960 if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
1961 maxSdkVersion = val.data;
1962 }
1963 }
1964
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07001965 sa.recycle();
1966
Christopher Tatefb0676a2013-09-16 16:34:52 -07001967 if ((maxSdkVersion == 0) || (maxSdkVersion >= Build.VERSION.RESOURCES_SDK_INT)) {
1968 if (name != null) {
1969 int index = pkg.requestedPermissions.indexOf(name);
1970 if (index == -1) {
1971 pkg.requestedPermissions.add(name.intern());
Christopher Tatefb0676a2013-09-16 16:34:52 -07001972 } else {
Svetoslav96a77162015-04-03 13:58:33 -07001973 Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
1974 + name + " in package: " + pkg.packageName + " at: "
1975 + parser.getPositionDescription());
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07001976 }
1977 }
1978 }
1979
1980 XmlUtils.skipCurrentTag(parser);
1981 return true;
1982 }
1983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001984 private static String buildClassName(String pkg, CharSequence clsSeq,
1985 String[] outError) {
1986 if (clsSeq == null || clsSeq.length() <= 0) {
1987 outError[0] = "Empty class name in package " + pkg;
1988 return null;
1989 }
1990 String cls = clsSeq.toString();
1991 char c = cls.charAt(0);
1992 if (c == '.') {
1993 return (pkg + cls).intern();
1994 }
1995 if (cls.indexOf('.') < 0) {
1996 StringBuilder b = new StringBuilder(pkg);
1997 b.append('.');
1998 b.append(cls);
1999 return b.toString().intern();
2000 }
2001 if (c >= 'a' && c <= 'z') {
2002 return cls.intern();
2003 }
2004 outError[0] = "Bad class name " + cls + " in package " + pkg;
2005 return null;
2006 }
2007
2008 private static String buildCompoundName(String pkg,
2009 CharSequence procSeq, String type, String[] outError) {
2010 String proc = procSeq.toString();
2011 char c = proc.charAt(0);
2012 if (pkg != null && c == ':') {
2013 if (proc.length() < 2) {
2014 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
2015 + ": must be at least two characters";
2016 return null;
2017 }
2018 String subName = proc.substring(1);
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002019 String nameError = validateName(subName, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002020 if (nameError != null) {
2021 outError[0] = "Invalid " + type + " name " + proc + " in package "
2022 + pkg + ": " + nameError;
2023 return null;
2024 }
2025 return (pkg + proc).intern();
2026 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002027 String nameError = validateName(proc, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002028 if (nameError != null && !"system".equals(proc)) {
2029 outError[0] = "Invalid " + type + " name " + proc + " in package "
2030 + pkg + ": " + nameError;
2031 return null;
2032 }
2033 return proc.intern();
2034 }
2035
2036 private static String buildProcessName(String pkg, String defProc,
2037 CharSequence procSeq, int flags, String[] separateProcesses,
2038 String[] outError) {
2039 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
2040 return defProc != null ? defProc : pkg;
2041 }
2042 if (separateProcesses != null) {
2043 for (int i=separateProcesses.length-1; i>=0; i--) {
2044 String sp = separateProcesses[i];
2045 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
2046 return pkg;
2047 }
2048 }
2049 }
2050 if (procSeq == null || procSeq.length() <= 0) {
2051 return defProc;
2052 }
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002053 return buildCompoundName(pkg, procSeq, "process", outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002054 }
2055
2056 private static String buildTaskAffinityName(String pkg, String defProc,
2057 CharSequence procSeq, String[] outError) {
2058 if (procSeq == null) {
2059 return defProc;
2060 }
2061 if (procSeq.length() <= 0) {
2062 return null;
2063 }
2064 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
2065 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002066
dcashman989eb3712014-06-17 12:56:12 -07002067 private boolean parseKeySets(Package owner, Resources res,
Geremy Condraf1bcca82013-01-07 22:35:24 -08002068 XmlPullParser parser, AttributeSet attrs, String[] outError)
2069 throws XmlPullParserException, IOException {
dcashman989eb3712014-06-17 12:56:12 -07002070 // we've encountered the 'key-sets' tag
Geremy Condraf1bcca82013-01-07 22:35:24 -08002071 // all the keys and keysets that we want must be defined here
2072 // so we're going to iterate over the parser and pull out the things we want
2073 int outerDepth = parser.getDepth();
dcashman989eb3712014-06-17 12:56:12 -07002074 int currentKeySetDepth = -1;
Geremy Condraf1bcca82013-01-07 22:35:24 -08002075 int type;
dcashman989eb3712014-06-17 12:56:12 -07002076 String currentKeySet = null;
2077 ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
2078 ArraySet<String> upgradeKeySets = new ArraySet<String>();
2079 ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
2080 ArraySet<String> improperKeySets = new ArraySet<String>();
Geremy Condraf1bcca82013-01-07 22:35:24 -08002081 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2082 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2083 if (type == XmlPullParser.END_TAG) {
dcashman989eb3712014-06-17 12:56:12 -07002084 if (parser.getDepth() == currentKeySetDepth) {
2085 currentKeySet = null;
2086 currentKeySetDepth = -1;
Kenny Root37dca152013-07-10 14:01:49 -07002087 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002088 continue;
2089 }
dcashman989eb3712014-06-17 12:56:12 -07002090 String tagName = parser.getName();
2091 if (tagName.equals("key-set")) {
2092 if (currentKeySet != null) {
dcashman5db0cd42015-05-22 15:24:40 -07002093 outError[0] = "Improperly nested 'key-set' tag at "
2094 + parser.getPositionDescription();
2095 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002096 return false;
2097 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002098 final TypedArray sa = res.obtainAttributes(attrs,
dcashman989eb3712014-06-17 12:56:12 -07002099 com.android.internal.R.styleable.AndroidManifestKeySet);
2100 final String keysetName = sa.getNonResourceString(
2101 com.android.internal.R.styleable.AndroidManifestKeySet_name);
2102 definedKeySets.put(keysetName, new ArraySet<String>());
2103 currentKeySet = keysetName;
2104 currentKeySetDepth = parser.getDepth();
2105 sa.recycle();
2106 } else if (tagName.equals("public-key")) {
2107 if (currentKeySet == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002108 outError[0] = "Improperly nested 'key-set' tag at "
2109 + parser.getPositionDescription();
2110 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002111 return false;
2112 }
2113 final TypedArray sa = res.obtainAttributes(attrs,
2114 com.android.internal.R.styleable.AndroidManifestPublicKey);
2115 final String publicKeyName = sa.getNonResourceString(
2116 com.android.internal.R.styleable.AndroidManifestPublicKey_name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002117 final String encodedKey = sa.getNonResourceString(
dcashman989eb3712014-06-17 12:56:12 -07002118 com.android.internal.R.styleable.AndroidManifestPublicKey_value);
2119 if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002120 outError[0] = "'public-key' " + publicKeyName + " must define a public-key value"
2121 + " on first use at " + parser.getPositionDescription();
2122 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Kenny Root37dca152013-07-10 14:01:49 -07002123 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002124 return false;
2125 } else if (encodedKey != null) {
2126 PublicKey currentKey = parsePublicKey(encodedKey);
2127 if (currentKey == null) {
2128 Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
2129 + parser.getPositionDescription() + " key-set " + currentKeySet
2130 + " will not be added to the package's defined key-sets.");
2131 sa.recycle();
2132 improperKeySets.add(currentKeySet);
2133 XmlUtils.skipCurrentTag(parser);
2134 continue;
2135 }
2136 if (publicKeys.get(publicKeyName) == null
2137 || publicKeys.get(publicKeyName).equals(currentKey)) {
2138
2139 /* public-key first definition, or matches old definition */
2140 publicKeys.put(publicKeyName, currentKey);
2141 } else {
dcashman5db0cd42015-05-22 15:24:40 -07002142 outError[0] = "Value of 'public-key' " + publicKeyName
dcashman989eb3712014-06-17 12:56:12 -07002143 + " conflicts with previously defined value at "
dcashman5db0cd42015-05-22 15:24:40 -07002144 + parser.getPositionDescription();
2145 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002146 sa.recycle();
2147 return false;
2148 }
Kenny Root37dca152013-07-10 14:01:49 -07002149 }
dcashman989eb3712014-06-17 12:56:12 -07002150 definedKeySets.get(currentKeySet).add(publicKeyName);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002151 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002152 XmlUtils.skipCurrentTag(parser);
2153 } else if (tagName.equals("upgrade-key-set")) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08002154 final TypedArray sa = res.obtainAttributes(attrs,
dcashman989eb3712014-06-17 12:56:12 -07002155 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
2156 String name = sa.getNonResourceString(
2157 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
2158 upgradeKeySets.add(name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002159 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002160 XmlUtils.skipCurrentTag(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002161 } else if (RIGID_PARSER) {
dcashman5db0cd42015-05-22 15:24:40 -07002162 outError[0] = "Bad element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08002163 + " at " + mArchiveSourcePath + " "
dcashman5db0cd42015-05-22 15:24:40 -07002164 + parser.getPositionDescription();
2165 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Geremy Condraf1bcca82013-01-07 22:35:24 -08002166 return false;
2167 } else {
dcashman989eb3712014-06-17 12:56:12 -07002168 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08002169 + " at " + mArchiveSourcePath + " "
2170 + parser.getPositionDescription());
2171 XmlUtils.skipCurrentTag(parser);
2172 continue;
2173 }
2174 }
dcashman989eb3712014-06-17 12:56:12 -07002175 Set<String> publicKeyNames = publicKeys.keySet();
2176 if (publicKeyNames.removeAll(definedKeySets.keySet())) {
dcashman5db0cd42015-05-22 15:24:40 -07002177 outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
2178 + "'key-set' and 'public-key' names must be distinct.";
2179 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002180 return false;
2181 }
2182 owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
2183 for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) {
2184 final String keySetName = e.getKey();
2185 if (e.getValue().size() == 0) {
2186 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
2187 + "'key-set' " + keySetName + " has no valid associated 'public-key'."
2188 + " Not including in package's defined key-sets.");
2189 continue;
2190 } else if (improperKeySets.contains(keySetName)) {
2191 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
2192 + "'key-set' " + keySetName + " contained improper 'public-key'"
2193 + " tags. Not including in package's defined key-sets.");
2194 continue;
2195 }
2196 owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
2197 for (String s : e.getValue()) {
2198 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
Geremy Condraf1bcca82013-01-07 22:35:24 -08002199 }
2200 }
dcashman989eb3712014-06-17 12:56:12 -07002201 if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
2202 owner.mUpgradeKeySets = upgradeKeySets;
2203 } else {
dcashman5db0cd42015-05-22 15:24:40 -07002204 outError[0] ="Package" + owner.packageName + " AndroidManifext.xml "
2205 + "does not define all 'upgrade-key-set's .";
2206 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002207 return false;
2208 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002209 return true;
2210 }
2211
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07002212 private PermissionGroup parsePermissionGroup(Package owner, int flags, Resources res,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002213 XmlPullParser parser, AttributeSet attrs, String[] outError)
2214 throws XmlPullParserException, IOException {
2215 PermissionGroup perm = new PermissionGroup(owner);
2216
2217 TypedArray sa = res.obtainAttributes(attrs,
2218 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
2219
2220 if (!parsePackageItemInfo(owner, perm.info, outError,
2221 "<permission-group>", sa,
2222 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
2223 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002224 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
Jose Limaf78e3122014-03-06 12:13:15 -08002225 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
2226 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002227 sa.recycle();
2228 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2229 return null;
2230 }
2231
2232 perm.info.descriptionRes = sa.getResourceId(
2233 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
2234 0);
Dianne Hackborn7454d3b2012-09-12 17:22:00 -07002235 perm.info.flags = sa.getInt(
2236 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07002237 perm.info.priority = sa.getInt(
2238 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
Dianne Hackborn99222d22012-05-06 16:30:15 -07002239 if (perm.info.priority > 0 && (flags&PARSE_IS_SYSTEM) == 0) {
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07002240 perm.info.priority = 0;
2241 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002242
2243 sa.recycle();
2244
2245 if (!parseAllMetaData(res, parser, attrs, "<permission-group>", perm,
2246 outError)) {
2247 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2248 return null;
2249 }
2250
2251 owner.permissionGroups.add(perm);
2252
2253 return perm;
2254 }
2255
2256 private Permission parsePermission(Package owner, Resources res,
2257 XmlPullParser parser, AttributeSet attrs, String[] outError)
2258 throws XmlPullParserException, IOException {
2259 Permission perm = new Permission(owner);
2260
2261 TypedArray sa = res.obtainAttributes(attrs,
2262 com.android.internal.R.styleable.AndroidManifestPermission);
2263
2264 if (!parsePackageItemInfo(owner, perm.info, outError,
2265 "<permission>", sa,
2266 com.android.internal.R.styleable.AndroidManifestPermission_name,
2267 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002268 com.android.internal.R.styleable.AndroidManifestPermission_icon,
Jose Limaf78e3122014-03-06 12:13:15 -08002269 com.android.internal.R.styleable.AndroidManifestPermission_logo,
2270 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002271 sa.recycle();
2272 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2273 return null;
2274 }
2275
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002276 // Note: don't allow this value to be a reference to a resource
2277 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002278 perm.info.group = sa.getNonResourceString(
2279 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
2280 if (perm.info.group != null) {
2281 perm.info.group = perm.info.group.intern();
2282 }
2283
2284 perm.info.descriptionRes = sa.getResourceId(
2285 com.android.internal.R.styleable.AndroidManifestPermission_description,
2286 0);
2287
2288 perm.info.protectionLevel = sa.getInt(
2289 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
2290 PermissionInfo.PROTECTION_NORMAL);
2291
Dianne Hackborn2ca2c872012-09-16 16:03:36 -07002292 perm.info.flags = sa.getInt(
2293 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
2294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002295 sa.recycle();
Dianne Hackborne639da72012-02-21 15:11:13 -08002296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002297 if (perm.info.protectionLevel == -1) {
2298 outError[0] = "<permission> does not specify protectionLevel";
2299 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2300 return null;
2301 }
Dianne Hackborne639da72012-02-21 15:11:13 -08002302
2303 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
2304
2305 if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_FLAGS) != 0) {
2306 if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
2307 PermissionInfo.PROTECTION_SIGNATURE) {
2308 outError[0] = "<permission> protectionLevel specifies a flag but is "
2309 + "not based on signature type";
2310 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2311 return null;
2312 }
2313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002314
2315 if (!parseAllMetaData(res, parser, attrs, "<permission>", perm,
2316 outError)) {
2317 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2318 return null;
2319 }
2320
2321 owner.permissions.add(perm);
2322
2323 return perm;
2324 }
2325
2326 private Permission parsePermissionTree(Package owner, Resources res,
2327 XmlPullParser parser, AttributeSet attrs, String[] outError)
2328 throws XmlPullParserException, IOException {
2329 Permission perm = new Permission(owner);
2330
2331 TypedArray sa = res.obtainAttributes(attrs,
2332 com.android.internal.R.styleable.AndroidManifestPermissionTree);
2333
2334 if (!parsePackageItemInfo(owner, perm.info, outError,
2335 "<permission-tree>", sa,
2336 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
2337 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002338 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
Jose Limaf78e3122014-03-06 12:13:15 -08002339 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
2340 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002341 sa.recycle();
2342 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2343 return null;
2344 }
2345
2346 sa.recycle();
2347
2348 int index = perm.info.name.indexOf('.');
2349 if (index > 0) {
2350 index = perm.info.name.indexOf('.', index+1);
2351 }
2352 if (index < 0) {
2353 outError[0] = "<permission-tree> name has less than three segments: "
2354 + perm.info.name;
2355 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2356 return null;
2357 }
2358
2359 perm.info.descriptionRes = 0;
2360 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
2361 perm.tree = true;
2362
2363 if (!parseAllMetaData(res, parser, attrs, "<permission-tree>", perm,
2364 outError)) {
2365 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2366 return null;
2367 }
2368
2369 owner.permissions.add(perm);
2370
2371 return perm;
2372 }
2373
2374 private Instrumentation parseInstrumentation(Package owner, Resources res,
2375 XmlPullParser parser, AttributeSet attrs, String[] outError)
2376 throws XmlPullParserException, IOException {
2377 TypedArray sa = res.obtainAttributes(attrs,
2378 com.android.internal.R.styleable.AndroidManifestInstrumentation);
2379
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002380 if (mParseInstrumentationArgs == null) {
2381 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
2382 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
2383 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002384 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
Jose Limaf78e3122014-03-06 12:13:15 -08002385 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
2386 com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002387 mParseInstrumentationArgs.tag = "<instrumentation>";
2388 }
2389
2390 mParseInstrumentationArgs.sa = sa;
2391
2392 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
2393 new InstrumentationInfo());
2394 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002395 sa.recycle();
2396 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2397 return null;
2398 }
2399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002400 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002401 // Note: don't allow this value to be a reference to a resource
2402 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002403 str = sa.getNonResourceString(
2404 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
2405 a.info.targetPackage = str != null ? str.intern() : null;
2406
2407 a.info.handleProfiling = sa.getBoolean(
2408 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
2409 false);
2410
2411 a.info.functionalTest = sa.getBoolean(
2412 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
2413 false);
2414
2415 sa.recycle();
2416
2417 if (a.info.targetPackage == null) {
2418 outError[0] = "<instrumentation> does not specify targetPackage";
2419 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2420 return null;
2421 }
2422
2423 if (!parseAllMetaData(res, parser, attrs, "<instrumentation>", a,
2424 outError)) {
2425 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2426 return null;
2427 }
2428
2429 owner.instrumentation.add(a);
2430
2431 return a;
2432 }
2433
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002434 /**
2435 * Parse the {@code application} XML tree at the current parse location in a
2436 * <em>base APK</em> manifest.
2437 * <p>
2438 * When adding new features, carefully consider if they should also be
2439 * supported by split APKs.
2440 */
2441 private boolean parseBaseApplication(Package owner, Resources res,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002442 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
2443 throws XmlPullParserException, IOException {
2444 final ApplicationInfo ai = owner.applicationInfo;
2445 final String pkgName = owner.applicationInfo.packageName;
2446
2447 TypedArray sa = res.obtainAttributes(attrs,
2448 com.android.internal.R.styleable.AndroidManifestApplication);
2449
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002450 String name = sa.getNonConfigurationString(
2451 com.android.internal.R.styleable.AndroidManifestApplication_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002452 if (name != null) {
2453 ai.className = buildClassName(pkgName, name, outError);
2454 if (ai.className == null) {
2455 sa.recycle();
2456 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2457 return false;
2458 }
2459 }
2460
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002461 String manageSpaceActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002462 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
2463 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002464 if (manageSpaceActivity != null) {
2465 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
2466 outError);
2467 }
2468
Christopher Tate181fafa2009-05-14 11:12:14 -07002469 boolean allowBackup = sa.getBoolean(
2470 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
2471 if (allowBackup) {
2472 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07002473
Matthew Williams303650c2015-04-17 18:22:51 -07002474 // backupAgent, killAfterRestore, fullBackupContent and restoreAnyVersion are only
2475 // relevant if backup is possible for the given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002476 String backupAgent = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002477 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
2478 Configuration.NATIVE_CONFIG_VERSION);
Christopher Tate181fafa2009-05-14 11:12:14 -07002479 if (backupAgent != null) {
2480 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07002481 if (DEBUG_BACKUP) {
2482 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002483 + " from " + pkgName + "+" + backupAgent);
2484 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07002485
2486 if (sa.getBoolean(
2487 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
2488 true)) {
2489 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
2490 }
2491 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08002492 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
2493 false)) {
2494 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
2495 }
Christopher Tated1de2562014-06-17 17:12:35 -07002496 if (sa.getBoolean(
2497 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
2498 false)) {
2499 ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
2500 }
Christopher Tate181fafa2009-05-14 11:12:14 -07002501 }
Matthew Williams303650c2015-04-17 18:22:51 -07002502
2503 TypedValue v = sa.peekValue(
2504 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
2505 if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
2506 if (DEBUG_BACKUP) {
2507 Slog.v(TAG, "fullBackupContent specified as boolean=" +
2508 (v.data == 0 ? "false" : "true"));
2509 }
2510 // "false" => -1, "true" => 0
2511 ai.fullBackupContent = (v.data == 0 ? -1 : 0);
2512 }
2513 if (DEBUG_BACKUP) {
2514 Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
2515 }
Christopher Tate181fafa2009-05-14 11:12:14 -07002516 }
Christopher Tate4a627c72011-04-01 14:43:32 -07002517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002518 TypedValue v = sa.peekValue(
2519 com.android.internal.R.styleable.AndroidManifestApplication_label);
2520 if (v != null && (ai.labelRes=v.resourceId) == 0) {
2521 ai.nonLocalizedLabel = v.coerceToString();
2522 }
2523
2524 ai.icon = sa.getResourceId(
2525 com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
Adam Powell81cd2e92010-04-21 16:35:18 -07002526 ai.logo = sa.getResourceId(
2527 com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);
Jose Limaf78e3122014-03-06 12:13:15 -08002528 ai.banner = sa.getResourceId(
2529 com.android.internal.R.styleable.AndroidManifestApplication_banner, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002530 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08002531 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002532 ai.descriptionRes = sa.getResourceId(
2533 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
2534
2535 if ((flags&PARSE_IS_SYSTEM) != 0) {
2536 if (sa.getBoolean(
2537 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
2538 false)) {
2539 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
2540 }
Amith Yamasani0d8750d2013-05-01 15:25:28 -07002541 }
2542
2543 if (sa.getBoolean(
2544 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
2545 false)) {
2546 owner.mRequiredForAllUsers = true;
Amith Yamasanie993ae12013-04-15 13:42:57 -07002547 }
2548
2549 String restrictedAccountType = sa.getString(com.android.internal.R.styleable
2550 .AndroidManifestApplication_restrictedAccountType);
2551 if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
2552 owner.mRestrictedAccountType = restrictedAccountType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002553 }
2554
Amith Yamasaniccbe3892013-04-12 17:52:42 -07002555 String requiredAccountType = sa.getString(com.android.internal.R.styleable
2556 .AndroidManifestApplication_requiredAccountType);
2557 if (requiredAccountType != null && requiredAccountType.length() > 0) {
2558 owner.mRequiredAccountType = requiredAccountType;
2559 }
2560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002561 if (sa.getBoolean(
2562 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
2563 false)) {
2564 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
2565 }
2566
2567 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07002568 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08002569 false)) {
2570 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
2571 }
2572
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002573 owner.baseHardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07002574 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07002575 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Alan Viveretted70b9e72015-05-27 14:29:20 -07002576 if (owner.baseHardwareAccelerated) {
2577 ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
2578 }
Romain Guy812ccbe2010-06-01 14:07:24 -07002579
2580 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002581 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
2582 true)) {
2583 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
2584 }
2585
2586 if (sa.getBoolean(
2587 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
2588 false)) {
2589 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
2590 }
2591
2592 if (sa.getBoolean(
2593 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
2594 true)) {
2595 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
2596 }
2597
Dianne Hackbornade3eca2009-05-11 18:54:45 -07002598 if (sa.getBoolean(
2599 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
Dianne Hackborne7fe35b2009-05-13 10:53:41 -07002600 false)) {
Dianne Hackbornade3eca2009-05-11 18:54:45 -07002601 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
2602 }
2603
Jason parksa3cdaa52011-01-13 14:15:43 -06002604 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08002605 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06002606 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08002607 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06002608 }
2609
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07002610 if (sa.getBoolean(
Alex Klyubin01a959d2015-03-18 10:05:45 -07002611 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
2612 true)) {
2613 ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
2614 }
2615
2616 if (sa.getBoolean(
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07002617 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
2618 false /* default is no RTL support*/)) {
2619 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
2620 }
2621
Narayan Kamath589a1bc2014-07-03 14:43:26 +01002622 if (sa.getBoolean(
2623 com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
2624 false)) {
2625 ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
2626 }
2627
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07002628 if (sa.getBoolean(
2629 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
2630 true)) {
2631 ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
2632 }
2633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002634 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002635 str = sa.getNonConfigurationString(
2636 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002637 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
2638
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002639 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
2640 str = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002641 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
2642 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002643 } else {
2644 // Some older apps have been seen to use a resource reference
2645 // here that on older builds was ignored (with a warning). We
2646 // need to continue to do this for them so they don't break.
2647 str = sa.getNonResourceString(
2648 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
2649 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002650 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
2651 str, outError);
2652
2653 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002654 CharSequence pname;
2655 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
2656 pname = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002657 com.android.internal.R.styleable.AndroidManifestApplication_process,
2658 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002659 } else {
2660 // Some older apps have been seen to use a resource reference
2661 // here that on older builds was ignored (with a warning). We
2662 // need to continue to do this for them so they don't break.
2663 pname = sa.getNonResourceString(
2664 com.android.internal.R.styleable.AndroidManifestApplication_process);
2665 }
2666 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002667 flags, mSeparateProcesses, outError);
2668
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002669 ai.enabled = sa.getBoolean(
2670 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002671
Jose Lima12d0b4c2014-03-14 16:55:12 -07002672 if (sa.getBoolean(
2673 com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
2674 ai.flags |= ApplicationInfo.FLAG_IS_GAME;
2675 }
2676
Dianne Hackborn02486b12010-08-26 14:18:37 -07002677 if (false) {
2678 if (sa.getBoolean(
2679 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
2680 false)) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08002681 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07002682
2683 // A heavy-weight application can not be in a custom process.
2684 // We can do direct compare because we intern all strings.
2685 if (ai.processName != null && ai.processName != ai.packageName) {
2686 outError[0] = "cantSaveState applications can not use custom processes";
2687 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07002688 }
2689 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002690 }
2691
Adam Powell269248d2011-08-02 10:26:54 -07002692 ai.uiOptions = sa.getInt(
2693 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
2694
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002695 sa.recycle();
2696
2697 if (outError[0] != null) {
2698 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2699 return false;
2700 }
2701
2702 final int innerDepth = parser.getDepth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002703 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07002704 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2705 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
2706 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002707 continue;
2708 }
2709
2710 String tagName = parser.getName();
2711 if (tagName.equals("activity")) {
Romain Guy529b60a2010-08-03 18:05:47 -07002712 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002713 owner.baseHardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 if (a == null) {
2715 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2716 return false;
2717 }
2718
2719 owner.activities.add(a);
2720
2721 } else if (tagName.equals("receiver")) {
Romain Guy529b60a2010-08-03 18:05:47 -07002722 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002723 if (a == null) {
2724 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2725 return false;
2726 }
2727
2728 owner.receivers.add(a);
2729
2730 } else if (tagName.equals("service")) {
2731 Service s = parseService(owner, res, parser, attrs, flags, outError);
2732 if (s == null) {
2733 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2734 return false;
2735 }
2736
2737 owner.services.add(s);
2738
2739 } else if (tagName.equals("provider")) {
2740 Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
2741 if (p == null) {
2742 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2743 return false;
2744 }
2745
2746 owner.providers.add(p);
2747
2748 } else if (tagName.equals("activity-alias")) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002749 Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002750 if (a == null) {
2751 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2752 return false;
2753 }
2754
2755 owner.activities.add(a);
2756
2757 } else if (parser.getName().equals("meta-data")) {
2758 // note: application meta-data is stored off to the side, so it can
2759 // remain null in the primary copy (we like to avoid extra copies because
2760 // it can be large)
2761 if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData,
2762 outError)) == null) {
2763 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2764 return false;
2765 }
2766
Dianne Hackbornc895be72013-03-11 17:48:43 -07002767 } else if (tagName.equals("library")) {
2768 sa = res.obtainAttributes(attrs,
2769 com.android.internal.R.styleable.AndroidManifestLibrary);
2770
2771 // Note: don't allow this value to be a reference to a resource
2772 // that may change.
2773 String lname = sa.getNonResourceString(
2774 com.android.internal.R.styleable.AndroidManifestLibrary_name);
2775
2776 sa.recycle();
2777
2778 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002779 lname = lname.intern();
2780 if (!ArrayUtils.contains(owner.libraryNames, lname)) {
2781 owner.libraryNames = ArrayUtils.add(owner.libraryNames, lname);
Dianne Hackbornc895be72013-03-11 17:48:43 -07002782 }
2783 }
2784
2785 XmlUtils.skipCurrentTag(parser);
2786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002787 } else if (tagName.equals("uses-library")) {
2788 sa = res.obtainAttributes(attrs,
2789 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
2790
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002791 // Note: don't allow this value to be a reference to a resource
2792 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002793 String lname = sa.getNonResourceString(
2794 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07002795 boolean req = sa.getBoolean(
2796 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
2797 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002798
2799 sa.recycle();
2800
Dianne Hackborn49237342009-08-27 20:08:01 -07002801 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002802 lname = lname.intern();
Dianne Hackborn49237342009-08-27 20:08:01 -07002803 if (req) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002804 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07002805 } else {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002806 owner.usesOptionalLibraries = ArrayUtils.add(
2807 owner.usesOptionalLibraries, lname);
2808 }
2809 }
2810
2811 XmlUtils.skipCurrentTag(parser);
2812
2813 } else if (tagName.equals("uses-package")) {
2814 // Dependencies for app installers; we don't currently try to
2815 // enforce this.
2816 XmlUtils.skipCurrentTag(parser);
2817
2818 } else {
2819 if (!RIGID_PARSER) {
2820 Slog.w(TAG, "Unknown element under <application>: " + tagName
2821 + " at " + mArchiveSourcePath + " "
2822 + parser.getPositionDescription());
2823 XmlUtils.skipCurrentTag(parser);
2824 continue;
2825 } else {
2826 outError[0] = "Bad element under <application>: " + tagName;
2827 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2828 return false;
2829 }
2830 }
2831 }
2832
Narayan Kamathb12dcfb2015-03-30 11:31:04 +01002833 modifySharedLibrariesForBackwardCompatibility(owner);
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00002834
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07002835 if (hasDomainURLs(owner)) {
2836 owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
2837 } else {
2838 owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
2839 }
2840
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002841 return true;
2842 }
2843
Narayan Kamathb12dcfb2015-03-30 11:31:04 +01002844 private static void modifySharedLibrariesForBackwardCompatibility(Package owner) {
2845 // "org.apache.http.legacy" is now a part of the boot classpath so it doesn't need
2846 // to be an explicit dependency.
2847 //
2848 // A future change will remove this library from the boot classpath, at which point
2849 // all apps that target SDK 21 and earlier will have it automatically added to their
2850 // dependency lists.
2851 owner.usesLibraries = ArrayUtils.remove(owner.usesLibraries, "org.apache.http.legacy");
2852 owner.usesOptionalLibraries = ArrayUtils.remove(owner.usesOptionalLibraries,
2853 "org.apache.http.legacy");
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00002854 }
2855
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002856 /**
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07002857 * 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 -07002858 */
2859 private static boolean hasDomainURLs(Package pkg) {
2860 if (pkg == null || pkg.activities == null) return false;
2861 final ArrayList<Activity> activities = pkg.activities;
2862 final int countActivities = activities.size();
2863 for (int n=0; n<countActivities; n++) {
2864 Activity activity = activities.get(n);
2865 ArrayList<ActivityIntentInfo> filters = activity.intents;
2866 if (filters == null) continue;
2867 final int countFilters = filters.size();
2868 for (int m=0; m<countFilters; m++) {
2869 ActivityIntentInfo aii = filters.get(m);
2870 if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07002871 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07002872 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
2873 aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
2874 return true;
2875 }
2876 }
2877 }
2878 return false;
2879 }
2880
2881 /**
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002882 * Parse the {@code application} XML tree at the current parse location in a
2883 * <em>split APK</em> manifest.
2884 * <p>
2885 * Note that split APKs have many more restrictions on what they're capable
2886 * of doing, so many valid features of a base APK have been carefully
2887 * omitted here.
2888 */
2889 private boolean parseSplitApplication(Package owner, Resources res, XmlPullParser parser,
2890 AttributeSet attrs, int flags, int splitIndex, String[] outError)
2891 throws XmlPullParserException, IOException {
2892 TypedArray sa = res.obtainAttributes(attrs,
2893 com.android.internal.R.styleable.AndroidManifestApplication);
2894
2895 if (sa.getBoolean(
2896 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
2897 owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
2898 }
2899
2900 final int innerDepth = parser.getDepth();
2901 int type;
2902 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2903 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
2904 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2905 continue;
2906 }
2907
2908 String tagName = parser.getName();
2909 if (tagName.equals("activity")) {
2910 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
2911 owner.baseHardwareAccelerated);
2912 if (a == null) {
2913 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2914 return false;
2915 }
2916
2917 owner.activities.add(a);
2918
2919 } else if (tagName.equals("receiver")) {
2920 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
2921 if (a == null) {
2922 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2923 return false;
2924 }
2925
2926 owner.receivers.add(a);
2927
2928 } else if (tagName.equals("service")) {
2929 Service s = parseService(owner, res, parser, attrs, flags, outError);
2930 if (s == null) {
2931 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2932 return false;
2933 }
2934
2935 owner.services.add(s);
2936
2937 } else if (tagName.equals("provider")) {
2938 Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
2939 if (p == null) {
2940 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2941 return false;
2942 }
2943
2944 owner.providers.add(p);
2945
2946 } else if (tagName.equals("activity-alias")) {
2947 Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
2948 if (a == null) {
2949 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2950 return false;
2951 }
2952
2953 owner.activities.add(a);
2954
2955 } else if (parser.getName().equals("meta-data")) {
2956 // note: application meta-data is stored off to the side, so it can
2957 // remain null in the primary copy (we like to avoid extra copies because
2958 // it can be large)
2959 if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData,
2960 outError)) == null) {
2961 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2962 return false;
2963 }
2964
2965 } else if (tagName.equals("uses-library")) {
2966 sa = res.obtainAttributes(attrs,
2967 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
2968
2969 // Note: don't allow this value to be a reference to a resource
2970 // that may change.
2971 String lname = sa.getNonResourceString(
2972 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
2973 boolean req = sa.getBoolean(
2974 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
2975 true);
2976
2977 sa.recycle();
2978
2979 if (lname != null) {
2980 lname = lname.intern();
2981 if (req) {
2982 // Upgrade to treat as stronger constraint
2983 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
2984 owner.usesOptionalLibraries = ArrayUtils.remove(
2985 owner.usesOptionalLibraries, lname);
2986 } else {
2987 // Ignore if someone already defined as required
2988 if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
2989 owner.usesOptionalLibraries = ArrayUtils.add(
2990 owner.usesOptionalLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07002991 }
2992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002993 }
2994
2995 XmlUtils.skipCurrentTag(parser);
2996
Dianne Hackborncef65ee2010-09-30 18:27:22 -07002997 } else if (tagName.equals("uses-package")) {
2998 // Dependencies for app installers; we don't currently try to
2999 // enforce this.
3000 XmlUtils.skipCurrentTag(parser);
3001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003002 } else {
3003 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003004 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003005 + " at " + mArchiveSourcePath + " "
3006 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003007 XmlUtils.skipCurrentTag(parser);
3008 continue;
3009 } else {
3010 outError[0] = "Bad element under <application>: " + tagName;
3011 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3012 return false;
3013 }
3014 }
3015 }
3016
3017 return true;
3018 }
3019
3020 private boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
3021 String[] outError, String tag, TypedArray sa,
Jose Limaf78e3122014-03-06 12:13:15 -08003022 int nameRes, int labelRes, int iconRes, int logoRes, int bannerRes) {
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003023 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003024 if (name == null) {
3025 outError[0] = tag + " does not specify android:name";
3026 return false;
3027 }
3028
3029 outInfo.name
3030 = buildClassName(owner.applicationInfo.packageName, name, outError);
3031 if (outInfo.name == null) {
3032 return false;
3033 }
3034
3035 int iconVal = sa.getResourceId(iconRes, 0);
3036 if (iconVal != 0) {
3037 outInfo.icon = iconVal;
3038 outInfo.nonLocalizedLabel = null;
3039 }
Adam Powell81cd2e92010-04-21 16:35:18 -07003040
3041 int logoVal = sa.getResourceId(logoRes, 0);
3042 if (logoVal != 0) {
3043 outInfo.logo = logoVal;
3044 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003045
Jose Limaf78e3122014-03-06 12:13:15 -08003046 int bannerVal = sa.getResourceId(bannerRes, 0);
3047 if (bannerVal != 0) {
3048 outInfo.banner = bannerVal;
3049 }
3050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051 TypedValue v = sa.peekValue(labelRes);
3052 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
3053 outInfo.nonLocalizedLabel = v.coerceToString();
3054 }
3055
3056 outInfo.packageName = owner.packageName;
3057
3058 return true;
3059 }
3060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003061 private Activity parseActivity(Package owner, Resources res,
3062 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError,
Romain Guy529b60a2010-08-03 18:05:47 -07003063 boolean receiver, boolean hardwareAccelerated)
3064 throws XmlPullParserException, IOException {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003065 TypedArray sa = res.obtainAttributes(attrs, R.styleable.AndroidManifestActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003067 if (mParseActivityArgs == null) {
3068 mParseActivityArgs = new ParseComponentArgs(owner, outError,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003069 R.styleable.AndroidManifestActivity_name,
3070 R.styleable.AndroidManifestActivity_label,
3071 R.styleable.AndroidManifestActivity_icon,
3072 R.styleable.AndroidManifestActivity_logo,
3073 R.styleable.AndroidManifestActivity_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003074 mSeparateProcesses,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003075 R.styleable.AndroidManifestActivity_process,
3076 R.styleable.AndroidManifestActivity_description,
3077 R.styleable.AndroidManifestActivity_enabled);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003078 }
3079
3080 mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
3081 mParseActivityArgs.sa = sa;
3082 mParseActivityArgs.flags = flags;
3083
3084 Activity a = new Activity(mParseActivityArgs, new ActivityInfo());
3085 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 sa.recycle();
3087 return null;
3088 }
3089
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003090 boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003091 if (setExported) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003092 a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003093 }
3094
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003095 a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003096
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003097 a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
Adam Powell269248d2011-08-02 10:26:54 -07003098 a.info.applicationInfo.uiOptions);
3099
Adam Powelldd8fab22012-03-22 17:47:27 -07003100 String parentName = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003101 R.styleable.AndroidManifestActivity_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003102 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07003103 if (parentName != null) {
3104 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
3105 if (outError[0] == null) {
3106 a.info.parentActivityName = parentClassName;
3107 } else {
3108 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
3109 parentName);
3110 outError[0] = null;
3111 }
3112 }
3113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003114 String str;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003115 str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003116 if (str == null) {
3117 a.info.permission = owner.applicationInfo.permission;
3118 } else {
3119 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
3120 }
3121
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003122 str = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003123 R.styleable.AndroidManifestActivity_taskAffinity,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003124 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003125 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
3126 owner.applicationInfo.taskAffinity, str, outError);
3127
3128 a.info.flags = 0;
3129 if (sa.getBoolean(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003130 R.styleable.AndroidManifestActivity_multiprocess, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003131 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
3132 }
3133
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003134 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003135 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
3136 }
3137
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003138 if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003139 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
3140 }
3141
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003142 if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003143 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
3144 }
3145
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003146 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003147 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
3148 }
3149
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003150 if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003151 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
3152 }
3153
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003154 if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003155 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
3156 }
3157
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003158 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003159 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
3160 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
3161 }
3162
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003163 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
Dianne Hackbornffa42482009-09-23 22:20:11 -07003164 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
3165 }
3166
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07003167 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
3168 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
3169 a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Craig Mautner5962b122012-10-05 14:45:52 -07003170 }
3171
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003172 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
Daniel Sandler613dde42010-06-21 13:46:39 -04003173 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
3174 }
Craig Mautner5962b122012-10-05 14:45:52 -07003175
Fyodor Kupolov4f5de342015-08-25 10:08:45 -07003176 if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
3177 a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
Fyodor Kupolov703d1c42015-01-27 11:59:00 -08003178 }
3179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003180 if (!receiver) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003181 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07003182 hardwareAccelerated)) {
3183 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
3184 }
3185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003186 a.info.launchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003187 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
Craig Mautner2dac0562014-05-06 09:06:44 -07003188 a.info.documentLaunchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003189 R.styleable.AndroidManifestActivity_documentLaunchMode,
Craig Mautner2dac0562014-05-06 09:06:44 -07003190 ActivityInfo.DOCUMENT_LAUNCH_NONE);
Craig Mautnerffcfcaa2014-06-05 09:54:38 -07003191 a.info.maxRecents = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003192 R.styleable.AndroidManifestActivity_maxRecents,
Dianne Hackborn852975d2014-08-22 17:42:43 -07003193 ActivityManager.getDefaultAppRecentsLimitStatic());
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003194 a.info.configChanges = sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003195 a.info.softInputMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003196 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
Craig Mautner2dac0562014-05-06 09:06:44 -07003197
Craig Mautner43e52ed2014-06-16 17:18:52 -07003198 a.info.persistableMode = sa.getInteger(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003199 R.styleable.AndroidManifestActivity_persistableMode,
Craig Mautner43e52ed2014-06-16 17:18:52 -07003200 ActivityInfo.PERSIST_ROOT_ONLY);
Craig Mautner2dac0562014-05-06 09:06:44 -07003201
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003202 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07003203 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
3204 }
3205
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003206 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07003207 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
3208 }
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07003209
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003210 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07003211 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
3212 }
Dianne Hackborna4e102e2014-09-04 22:52:27 -07003213
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003214 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
Dianne Hackborna4e102e2014-09-04 22:52:27 -07003215 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
3216 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003217
3218 a.info.resizeable = sa.getBoolean(
Wale Ogunwale6a591362015-10-05 20:18:27 -07003219 R.styleable.AndroidManifestActivity_resizeableActivity,
3220 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N);
3221
3222 a.info.screenOrientation = sa.getInt(
3223 R.styleable.AndroidManifestActivity_screenOrientation,
3224 ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
Craig Mautner15df08a2015-04-01 12:17:18 -07003225
3226 a.info.lockTaskLaunchMode =
3227 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003228 } else {
3229 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
3230 a.info.configChanges = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003231
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003232 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07003233 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003234 if (a.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003235 Slog.w(TAG, "Activity exported request ignored due to singleUser: "
3236 + a.className + " at " + mArchiveSourcePath + " "
3237 + parser.getPositionDescription());
3238 a.info.exported = false;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003239 setExported = true;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003240 }
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003241 }
3242 }
3243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003244 sa.recycle();
3245
Alex Klyubinb9f8a522015-02-03 11:12:59 -08003246 if (receiver && (owner.applicationInfo.privateFlags
3247 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07003248 // A heavy-weight application can not have receives in its main process
3249 // We can do direct compare because we intern all strings.
3250 if (a.info.processName == owner.packageName) {
3251 outError[0] = "Heavy-weight applications can not have receivers in main process";
3252 }
3253 }
3254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003255 if (outError[0] != null) {
3256 return null;
3257 }
3258
3259 int outerDepth = parser.getDepth();
3260 int type;
3261 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3262 && (type != XmlPullParser.END_TAG
3263 || parser.getDepth() > outerDepth)) {
3264 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3265 continue;
3266 }
3267
3268 if (parser.getName().equals("intent-filter")) {
3269 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08003270 if (!parseIntent(res, parser, attrs, true, true, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003271 return null;
3272 }
3273 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003274 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07003275 + mArchiveSourcePath + " "
3276 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003277 } else {
3278 a.intents.add(intent);
3279 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07003280 } else if (!receiver && parser.getName().equals("preferred")) {
3281 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08003282 if (!parseIntent(res, parser, attrs, false, false, intent, outError)) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07003283 return null;
3284 }
3285 if (intent.countActions() == 0) {
3286 Slog.w(TAG, "No actions in preferred at "
3287 + mArchiveSourcePath + " "
3288 + parser.getPositionDescription());
3289 } else {
3290 if (owner.preferredActivityFilters == null) {
3291 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
3292 }
3293 owner.preferredActivityFilters.add(intent);
3294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003295 } else if (parser.getName().equals("meta-data")) {
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003296 if ((a.metaData = parseMetaData(res, parser, attrs, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003297 outError)) == null) {
3298 return null;
3299 }
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003300 } else if (!receiver && parser.getName().equals("initial-layout")) {
3301 parseInitialLayout(res, attrs, a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003302 } else {
3303 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003304 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003305 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003306 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003307 + " at " + mArchiveSourcePath + " "
3308 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003309 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07003310 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003311 + " at " + mArchiveSourcePath + " "
3312 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003313 }
3314 XmlUtils.skipCurrentTag(parser);
3315 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003316 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07003317 if (receiver) {
3318 outError[0] = "Bad element under <receiver>: " + parser.getName();
3319 } else {
3320 outError[0] = "Bad element under <activity>: " + parser.getName();
3321 }
3322 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003323 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 }
3325 }
3326
3327 if (!setExported) {
3328 a.info.exported = a.intents.size() > 0;
3329 }
3330
3331 return a;
3332 }
3333
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003334 private void parseInitialLayout(Resources res, AttributeSet attrs, Activity a) {
3335 TypedArray sw = res.obtainAttributes(attrs,
3336 com.android.internal.R.styleable.AndroidManifestInitialLayout);
3337 int width = -1;
3338 float widthFraction = -1f;
3339 int height = -1;
3340 float heightFraction = -1f;
3341 final int widthType = sw.getType(
Filip Gruszczynski9b1ce522015-08-20 18:37:19 -07003342 com.android.internal.R.styleable.AndroidManifestInitialLayout_activityWidth);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003343 if (widthType == TypedValue.TYPE_FRACTION) {
3344 widthFraction = sw.getFraction(
Filip Gruszczynski9b1ce522015-08-20 18:37:19 -07003345 com.android.internal.R.styleable.AndroidManifestInitialLayout_activityWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003346 1, 1, -1);
3347 } else if (widthType == TypedValue.TYPE_DIMENSION) {
3348 width = sw.getDimensionPixelSize(
Filip Gruszczynski9b1ce522015-08-20 18:37:19 -07003349 com.android.internal.R.styleable.AndroidManifestInitialLayout_activityWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003350 -1);
3351 }
3352 final int heightType = sw.getType(
Filip Gruszczynski9b1ce522015-08-20 18:37:19 -07003353 com.android.internal.R.styleable.AndroidManifestInitialLayout_activityHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003354 if (heightType == TypedValue.TYPE_FRACTION) {
3355 heightFraction = sw.getFraction(
Filip Gruszczynski9b1ce522015-08-20 18:37:19 -07003356 com.android.internal.R.styleable.AndroidManifestInitialLayout_activityHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003357 1, 1, -1);
3358 } else if (heightType == TypedValue.TYPE_DIMENSION) {
3359 height = sw.getDimensionPixelSize(
Filip Gruszczynski9b1ce522015-08-20 18:37:19 -07003360 com.android.internal.R.styleable.AndroidManifestInitialLayout_activityHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003361 -1);
3362 }
3363 int gravity = sw.getInt(
3364 com.android.internal.R.styleable.AndroidManifestInitialLayout_gravity,
3365 Gravity.CENTER);
3366 sw.recycle();
3367 a.info.initialLayout = new ActivityInfo.InitialLayout(width, widthFraction,
3368 height, heightFraction, gravity);
3369 }
3370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003371 private Activity parseActivityAlias(Package owner, Resources res,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003372 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
3373 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003374 TypedArray sa = res.obtainAttributes(attrs,
3375 com.android.internal.R.styleable.AndroidManifestActivityAlias);
3376
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003377 String targetActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003378 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
3379 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003380 if (targetActivity == null) {
3381 outError[0] = "<activity-alias> does not specify android:targetActivity";
3382 sa.recycle();
3383 return null;
3384 }
3385
3386 targetActivity = buildClassName(owner.applicationInfo.packageName,
3387 targetActivity, outError);
3388 if (targetActivity == null) {
3389 sa.recycle();
3390 return null;
3391 }
3392
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003393 if (mParseActivityAliasArgs == null) {
3394 mParseActivityAliasArgs = new ParseComponentArgs(owner, outError,
3395 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
3396 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
3397 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07003398 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08003399 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003400 mSeparateProcesses,
3401 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003402 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003403 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
3404 mParseActivityAliasArgs.tag = "<activity-alias>";
3405 }
3406
3407 mParseActivityAliasArgs.sa = sa;
3408 mParseActivityAliasArgs.flags = flags;
3409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003410 Activity target = null;
3411
3412 final int NA = owner.activities.size();
3413 for (int i=0; i<NA; i++) {
3414 Activity t = owner.activities.get(i);
3415 if (targetActivity.equals(t.info.name)) {
3416 target = t;
3417 break;
3418 }
3419 }
3420
3421 if (target == null) {
3422 outError[0] = "<activity-alias> target activity " + targetActivity
3423 + " not found in manifest";
3424 sa.recycle();
3425 return null;
3426 }
3427
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003428 ActivityInfo info = new ActivityInfo();
3429 info.targetActivity = targetActivity;
3430 info.configChanges = target.info.configChanges;
3431 info.flags = target.info.flags;
3432 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07003433 info.logo = target.info.logo;
Jose Limaf78e3122014-03-06 12:13:15 -08003434 info.banner = target.info.banner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003435 info.labelRes = target.info.labelRes;
3436 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
3437 info.launchMode = target.info.launchMode;
Yao Chen597ad3f2015-06-09 16:00:14 -07003438 info.lockTaskLaunchMode = target.info.lockTaskLaunchMode;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003439 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003440 if (info.descriptionRes == 0) {
3441 info.descriptionRes = target.info.descriptionRes;
3442 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003443 info.screenOrientation = target.info.screenOrientation;
3444 info.taskAffinity = target.info.taskAffinity;
3445 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07003446 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07003447 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07003448 info.parentActivityName = target.info.parentActivityName;
Craig Mautner8307ea72014-09-11 15:03:53 -07003449 info.maxRecents = target.info.maxRecents;
Filip Gruszczynski9b1ce522015-08-20 18:37:19 -07003450 info.initialLayout = target.info.initialLayout;
Craig Mautner8307ea72014-09-11 15:03:53 -07003451
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003452 Activity a = new Activity(mParseActivityAliasArgs, info);
3453 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003454 sa.recycle();
3455 return null;
3456 }
3457
3458 final boolean setExported = sa.hasValue(
3459 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
3460 if (setExported) {
3461 a.info.exported = sa.getBoolean(
3462 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
3463 }
3464
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003465 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003466 str = sa.getNonConfigurationString(
3467 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 if (str != null) {
3469 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
3470 }
3471
Adam Powelldd8fab22012-03-22 17:47:27 -07003472 String parentName = sa.getNonConfigurationString(
3473 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003474 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07003475 if (parentName != null) {
3476 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
3477 if (outError[0] == null) {
3478 a.info.parentActivityName = parentClassName;
3479 } else {
3480 Log.e(TAG, "Activity alias " + a.info.name +
3481 " specified invalid parentActivityName " + parentName);
3482 outError[0] = null;
3483 }
3484 }
3485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003486 sa.recycle();
3487
3488 if (outError[0] != null) {
3489 return null;
3490 }
3491
3492 int outerDepth = parser.getDepth();
3493 int type;
3494 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3495 && (type != XmlPullParser.END_TAG
3496 || parser.getDepth() > outerDepth)) {
3497 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3498 continue;
3499 }
3500
3501 if (parser.getName().equals("intent-filter")) {
3502 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08003503 if (!parseIntent(res, parser, attrs, true, true, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 return null;
3505 }
3506 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003507 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07003508 + mArchiveSourcePath + " "
3509 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003510 } else {
3511 a.intents.add(intent);
3512 }
3513 } else if (parser.getName().equals("meta-data")) {
3514 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
3515 outError)) == null) {
3516 return null;
3517 }
3518 } else {
3519 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003520 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003521 + " at " + mArchiveSourcePath + " "
3522 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003523 XmlUtils.skipCurrentTag(parser);
3524 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003525 } else {
3526 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
3527 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003528 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003529 }
3530 }
3531
3532 if (!setExported) {
3533 a.info.exported = a.intents.size() > 0;
3534 }
3535
3536 return a;
3537 }
3538
3539 private Provider parseProvider(Package owner, Resources res,
3540 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
3541 throws XmlPullParserException, IOException {
3542 TypedArray sa = res.obtainAttributes(attrs,
3543 com.android.internal.R.styleable.AndroidManifestProvider);
3544
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003545 if (mParseProviderArgs == null) {
3546 mParseProviderArgs = new ParseComponentArgs(owner, outError,
3547 com.android.internal.R.styleable.AndroidManifestProvider_name,
3548 com.android.internal.R.styleable.AndroidManifestProvider_label,
3549 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07003550 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08003551 com.android.internal.R.styleable.AndroidManifestProvider_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003552 mSeparateProcesses,
3553 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003554 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003555 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
3556 mParseProviderArgs.tag = "<provider>";
3557 }
3558
3559 mParseProviderArgs.sa = sa;
3560 mParseProviderArgs.flags = flags;
3561
3562 Provider p = new Provider(mParseProviderArgs, new ProviderInfo());
3563 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003564 sa.recycle();
3565 return null;
3566 }
3567
Nick Kralevichf097b162012-07-28 12:43:48 -07003568 boolean providerExportedDefault = false;
3569
3570 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
3571 // For compatibility, applications targeting API level 16 or lower
3572 // should have their content providers exported by default, unless they
3573 // specify otherwise.
3574 providerExportedDefault = true;
3575 }
3576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003577 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07003578 com.android.internal.R.styleable.AndroidManifestProvider_exported,
3579 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003581 String cpname = sa.getNonConfigurationString(
3582 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003583
3584 p.info.isSyncable = sa.getBoolean(
3585 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
3586 false);
3587
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003588 String permission = sa.getNonConfigurationString(
3589 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
3590 String str = sa.getNonConfigurationString(
3591 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003592 if (str == null) {
3593 str = permission;
3594 }
3595 if (str == null) {
3596 p.info.readPermission = owner.applicationInfo.permission;
3597 } else {
3598 p.info.readPermission =
3599 str.length() > 0 ? str.toString().intern() : null;
3600 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003601 str = sa.getNonConfigurationString(
3602 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003603 if (str == null) {
3604 str = permission;
3605 }
3606 if (str == null) {
3607 p.info.writePermission = owner.applicationInfo.permission;
3608 } else {
3609 p.info.writePermission =
3610 str.length() > 0 ? str.toString().intern() : null;
3611 }
3612
3613 p.info.grantUriPermissions = sa.getBoolean(
3614 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
3615 false);
3616
3617 p.info.multiprocess = sa.getBoolean(
3618 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
3619 false);
3620
3621 p.info.initOrder = sa.getInt(
3622 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
3623 0);
3624
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003625 p.info.flags = 0;
3626
3627 if (sa.getBoolean(
3628 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
3629 false)) {
3630 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003631 if (p.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003632 Slog.w(TAG, "Provider exported request ignored due to singleUser: "
3633 + p.className + " at " + mArchiveSourcePath + " "
3634 + parser.getPositionDescription());
3635 p.info.exported = false;
3636 }
3637 }
3638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003639 sa.recycle();
3640
Alex Klyubinb9f8a522015-02-03 11:12:59 -08003641 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
3642 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07003643 // A heavy-weight application can not have providers in its main process
3644 // We can do direct compare because we intern all strings.
3645 if (p.info.processName == owner.packageName) {
3646 outError[0] = "Heavy-weight applications can not have providers in main process";
3647 return null;
3648 }
3649 }
3650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003651 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07003652 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003653 return null;
3654 }
Dianne Hackborn1bc177c2014-12-03 10:20:30 -08003655 if (cpname.length() <= 0) {
3656 outError[0] = "<provider> has empty authorities attribute";
3657 return null;
3658 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003659 p.info.authority = cpname.intern();
3660
3661 if (!parseProviderTags(res, parser, attrs, p, outError)) {
3662 return null;
3663 }
3664
3665 return p;
3666 }
3667
3668 private boolean parseProviderTags(Resources res,
3669 XmlPullParser parser, AttributeSet attrs,
3670 Provider outInfo, String[] outError)
3671 throws XmlPullParserException, IOException {
3672 int outerDepth = parser.getDepth();
3673 int type;
3674 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3675 && (type != XmlPullParser.END_TAG
3676 || parser.getDepth() > outerDepth)) {
3677 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3678 continue;
3679 }
3680
Jeff Sharkey85f5f812013-10-07 10:16:12 -07003681 if (parser.getName().equals("intent-filter")) {
3682 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08003683 if (!parseIntent(res, parser, attrs, true, false, intent, outError)) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07003684 return false;
3685 }
3686 outInfo.intents.add(intent);
3687
3688 } else if (parser.getName().equals("meta-data")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003689 if ((outInfo.metaData=parseMetaData(res, parser, attrs,
3690 outInfo.metaData, outError)) == null) {
3691 return false;
3692 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003693
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003694 } else if (parser.getName().equals("grant-uri-permission")) {
3695 TypedArray sa = res.obtainAttributes(attrs,
3696 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
3697
3698 PatternMatcher pa = null;
3699
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003700 String str = sa.getNonConfigurationString(
3701 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003702 if (str != null) {
3703 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
3704 }
3705
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003706 str = sa.getNonConfigurationString(
3707 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003708 if (str != null) {
3709 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
3710 }
3711
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003712 str = sa.getNonConfigurationString(
3713 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003714 if (str != null) {
3715 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
3716 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003718 sa.recycle();
3719
3720 if (pa != null) {
3721 if (outInfo.info.uriPermissionPatterns == null) {
3722 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
3723 outInfo.info.uriPermissionPatterns[0] = pa;
3724 } else {
3725 final int N = outInfo.info.uriPermissionPatterns.length;
3726 PatternMatcher[] newp = new PatternMatcher[N+1];
3727 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
3728 newp[N] = pa;
3729 outInfo.info.uriPermissionPatterns = newp;
3730 }
3731 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003732 } else {
3733 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003734 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003735 + parser.getName() + " at " + mArchiveSourcePath + " "
3736 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003737 XmlUtils.skipCurrentTag(parser);
3738 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003739 } else {
3740 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
3741 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003742 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003743 }
3744 XmlUtils.skipCurrentTag(parser);
3745
3746 } else if (parser.getName().equals("path-permission")) {
3747 TypedArray sa = res.obtainAttributes(attrs,
3748 com.android.internal.R.styleable.AndroidManifestPathPermission);
3749
3750 PathPermission pa = null;
3751
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003752 String permission = sa.getNonConfigurationString(
3753 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
3754 String readPermission = sa.getNonConfigurationString(
3755 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003756 if (readPermission == null) {
3757 readPermission = permission;
3758 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003759 String writePermission = sa.getNonConfigurationString(
3760 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003761 if (writePermission == null) {
3762 writePermission = permission;
3763 }
3764
3765 boolean havePerm = false;
3766 if (readPermission != null) {
3767 readPermission = readPermission.intern();
3768 havePerm = true;
3769 }
3770 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00003771 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003772 havePerm = true;
3773 }
3774
3775 if (!havePerm) {
3776 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003777 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003778 + parser.getName() + " at " + mArchiveSourcePath + " "
3779 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003780 XmlUtils.skipCurrentTag(parser);
3781 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003782 } else {
3783 outError[0] = "No readPermission or writePermssion for <path-permission>";
3784 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003785 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003786 }
3787
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003788 String path = sa.getNonConfigurationString(
3789 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003790 if (path != null) {
3791 pa = new PathPermission(path,
3792 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
3793 }
3794
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003795 path = sa.getNonConfigurationString(
3796 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003797 if (path != null) {
3798 pa = new PathPermission(path,
3799 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
3800 }
3801
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003802 path = sa.getNonConfigurationString(
3803 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003804 if (path != null) {
3805 pa = new PathPermission(path,
3806 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
3807 }
3808
3809 sa.recycle();
3810
3811 if (pa != null) {
3812 if (outInfo.info.pathPermissions == null) {
3813 outInfo.info.pathPermissions = new PathPermission[1];
3814 outInfo.info.pathPermissions[0] = pa;
3815 } else {
3816 final int N = outInfo.info.pathPermissions.length;
3817 PathPermission[] newp = new PathPermission[N+1];
3818 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
3819 newp[N] = pa;
3820 outInfo.info.pathPermissions = newp;
3821 }
3822 } else {
3823 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003824 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003825 + parser.getName() + " at " + mArchiveSourcePath + " "
3826 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003827 XmlUtils.skipCurrentTag(parser);
3828 continue;
3829 }
3830 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
3831 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003832 }
3833 XmlUtils.skipCurrentTag(parser);
3834
3835 } else {
3836 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003837 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003838 + parser.getName() + " at " + mArchiveSourcePath + " "
3839 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003840 XmlUtils.skipCurrentTag(parser);
3841 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003842 } else {
3843 outError[0] = "Bad element under <provider>: " + parser.getName();
3844 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003845 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003846 }
3847 }
3848 return true;
3849 }
3850
3851 private Service parseService(Package owner, Resources res,
3852 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
3853 throws XmlPullParserException, IOException {
3854 TypedArray sa = res.obtainAttributes(attrs,
3855 com.android.internal.R.styleable.AndroidManifestService);
3856
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003857 if (mParseServiceArgs == null) {
3858 mParseServiceArgs = new ParseComponentArgs(owner, outError,
3859 com.android.internal.R.styleable.AndroidManifestService_name,
3860 com.android.internal.R.styleable.AndroidManifestService_label,
3861 com.android.internal.R.styleable.AndroidManifestService_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07003862 com.android.internal.R.styleable.AndroidManifestService_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08003863 com.android.internal.R.styleable.AndroidManifestService_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003864 mSeparateProcesses,
3865 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003866 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003867 com.android.internal.R.styleable.AndroidManifestService_enabled);
3868 mParseServiceArgs.tag = "<service>";
3869 }
3870
3871 mParseServiceArgs.sa = sa;
3872 mParseServiceArgs.flags = flags;
3873
3874 Service s = new Service(mParseServiceArgs, new ServiceInfo());
3875 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003876 sa.recycle();
3877 return null;
3878 }
3879
Dianne Hackbornb4163a62012-08-02 18:31:26 -07003880 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003881 com.android.internal.R.styleable.AndroidManifestService_exported);
3882 if (setExported) {
3883 s.info.exported = sa.getBoolean(
3884 com.android.internal.R.styleable.AndroidManifestService_exported, false);
3885 }
3886
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003887 String str = sa.getNonConfigurationString(
3888 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003889 if (str == null) {
3890 s.info.permission = owner.applicationInfo.permission;
3891 } else {
3892 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
3893 }
3894
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003895 s.info.flags = 0;
3896 if (sa.getBoolean(
3897 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
3898 false)) {
3899 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
3900 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08003901 if (sa.getBoolean(
3902 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
3903 false)) {
3904 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
3905 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07003906 if (sa.getBoolean(
3907 com.android.internal.R.styleable.AndroidManifestService_singleUser,
3908 false)) {
3909 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003910 if (s.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackbornb4163a62012-08-02 18:31:26 -07003911 Slog.w(TAG, "Service exported request ignored due to singleUser: "
3912 + s.className + " at " + mArchiveSourcePath + " "
3913 + parser.getPositionDescription());
3914 s.info.exported = false;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003915 setExported = true;
Dianne Hackbornb4163a62012-08-02 18:31:26 -07003916 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07003917 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003918
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003919 sa.recycle();
3920
Alex Klyubinb9f8a522015-02-03 11:12:59 -08003921 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
3922 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07003923 // A heavy-weight application can not have services in its main process
3924 // We can do direct compare because we intern all strings.
3925 if (s.info.processName == owner.packageName) {
3926 outError[0] = "Heavy-weight applications can not have services in main process";
3927 return null;
3928 }
3929 }
3930
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003931 int outerDepth = parser.getDepth();
3932 int type;
3933 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3934 && (type != XmlPullParser.END_TAG
3935 || parser.getDepth() > outerDepth)) {
3936 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3937 continue;
3938 }
3939
3940 if (parser.getName().equals("intent-filter")) {
3941 ServiceIntentInfo intent = new ServiceIntentInfo(s);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08003942 if (!parseIntent(res, parser, attrs, true, false, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003943 return null;
3944 }
3945
3946 s.intents.add(intent);
3947 } else if (parser.getName().equals("meta-data")) {
3948 if ((s.metaData=parseMetaData(res, parser, attrs, s.metaData,
3949 outError)) == null) {
3950 return null;
3951 }
3952 } else {
3953 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003954 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003955 + parser.getName() + " at " + mArchiveSourcePath + " "
3956 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003957 XmlUtils.skipCurrentTag(parser);
3958 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003959 } else {
3960 outError[0] = "Bad element under <service>: " + parser.getName();
3961 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003962 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003963 }
3964 }
3965
3966 if (!setExported) {
3967 s.info.exported = s.intents.size() > 0;
3968 }
3969
3970 return s;
3971 }
3972
3973 private boolean parseAllMetaData(Resources res,
3974 XmlPullParser parser, AttributeSet attrs, String tag,
Todd Kennedy27c24fb2015-09-17 16:49:25 -07003975 Component<?> outInfo, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003976 throws XmlPullParserException, IOException {
3977 int outerDepth = parser.getDepth();
3978 int type;
3979 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3980 && (type != XmlPullParser.END_TAG
3981 || parser.getDepth() > outerDepth)) {
3982 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3983 continue;
3984 }
3985
3986 if (parser.getName().equals("meta-data")) {
3987 if ((outInfo.metaData=parseMetaData(res, parser, attrs,
3988 outInfo.metaData, outError)) == null) {
3989 return false;
3990 }
3991 } else {
3992 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003993 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003994 + parser.getName() + " at " + mArchiveSourcePath + " "
3995 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003996 XmlUtils.skipCurrentTag(parser);
3997 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003998 } else {
3999 outError[0] = "Bad element under " + tag + ": " + parser.getName();
4000 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004001 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004002 }
4003 }
4004 return true;
4005 }
4006
4007 private Bundle parseMetaData(Resources res,
4008 XmlPullParser parser, AttributeSet attrs,
4009 Bundle data, String[] outError)
4010 throws XmlPullParserException, IOException {
4011
4012 TypedArray sa = res.obtainAttributes(attrs,
4013 com.android.internal.R.styleable.AndroidManifestMetaData);
4014
4015 if (data == null) {
4016 data = new Bundle();
4017 }
4018
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004019 String name = sa.getNonConfigurationString(
4020 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004021 if (name == null) {
4022 outError[0] = "<meta-data> requires an android:name attribute";
4023 sa.recycle();
4024 return null;
4025 }
4026
Dianne Hackborn854060af2009-07-09 18:14:31 -07004027 name = name.intern();
4028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004029 TypedValue v = sa.peekValue(
4030 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
4031 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004032 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004033 data.putInt(name, v.resourceId);
4034 } else {
4035 v = sa.peekValue(
4036 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07004037 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004038 if (v != null) {
4039 if (v.type == TypedValue.TYPE_STRING) {
4040 CharSequence cs = v.coerceToString();
Dianne Hackborn854060af2009-07-09 18:14:31 -07004041 data.putString(name, cs != null ? cs.toString().intern() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004042 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
4043 data.putBoolean(name, v.data != 0);
4044 } else if (v.type >= TypedValue.TYPE_FIRST_INT
4045 && v.type <= TypedValue.TYPE_LAST_INT) {
4046 data.putInt(name, v.data);
4047 } else if (v.type == TypedValue.TYPE_FLOAT) {
4048 data.putFloat(name, v.getFloat());
4049 } else {
4050 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004051 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004052 + parser.getName() + " at " + mArchiveSourcePath + " "
4053 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004054 } else {
4055 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
4056 data = null;
4057 }
4058 }
4059 } else {
4060 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
4061 data = null;
4062 }
4063 }
4064
4065 sa.recycle();
4066
4067 XmlUtils.skipCurrentTag(parser);
4068
4069 return data;
4070 }
4071
Kenny Root05ca4c92011-09-15 10:36:25 -07004072 private static VerifierInfo parseVerifier(Resources res, XmlPullParser parser,
Jeff Sharkey275e0852014-06-17 18:18:49 -07004073 AttributeSet attrs, int flags) {
Kenny Root05ca4c92011-09-15 10:36:25 -07004074 final TypedArray sa = res.obtainAttributes(attrs,
4075 com.android.internal.R.styleable.AndroidManifestPackageVerifier);
4076
4077 final String packageName = sa.getNonResourceString(
4078 com.android.internal.R.styleable.AndroidManifestPackageVerifier_name);
4079
4080 final String encodedPublicKey = sa.getNonResourceString(
4081 com.android.internal.R.styleable.AndroidManifestPackageVerifier_publicKey);
4082
4083 sa.recycle();
4084
4085 if (packageName == null || packageName.length() == 0) {
4086 Slog.i(TAG, "verifier package name was null; skipping");
4087 return null;
Kenny Root05ca4c92011-09-15 10:36:25 -07004088 }
4089
Christopher Tate30147332014-04-15 12:57:47 -07004090 final PublicKey publicKey = parsePublicKey(encodedPublicKey);
4091 if (publicKey == null) {
4092 Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
4093 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -08004094 }
4095
Christopher Tate30147332014-04-15 12:57:47 -07004096 return new VerifierInfo(packageName, publicKey);
Geremy Condraf1bcca82013-01-07 22:35:24 -08004097 }
4098
Christopher Tate30147332014-04-15 12:57:47 -07004099 public static final PublicKey parsePublicKey(final String encodedPublicKey) {
4100 if (encodedPublicKey == null) {
dcashman1616f302015-05-29 14:47:23 -07004101 Slog.w(TAG, "Could not parse null public key");
Christopher Tate30147332014-04-15 12:57:47 -07004102 return null;
4103 }
4104
Kenny Root05ca4c92011-09-15 10:36:25 -07004105 EncodedKeySpec keySpec;
4106 try {
4107 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
4108 keySpec = new X509EncodedKeySpec(encoded);
4109 } catch (IllegalArgumentException e) {
dcashman1616f302015-05-29 14:47:23 -07004110 Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07004111 return null;
4112 }
4113
4114 /* First try the key as an RSA key. */
4115 try {
4116 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08004117 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07004118 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07004119 Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07004120 } catch (InvalidKeySpecException e) {
4121 // Not a RSA public key.
4122 }
4123
dcashman1616f302015-05-29 14:47:23 -07004124 /* Now try it as a ECDSA key. */
4125 try {
4126 final KeyFactory keyFactory = KeyFactory.getInstance("EC");
4127 return keyFactory.generatePublic(keySpec);
4128 } catch (NoSuchAlgorithmException e) {
4129 Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build");
4130 } catch (InvalidKeySpecException e) {
4131 // Not a ECDSA public key.
4132 }
4133
Kenny Root05ca4c92011-09-15 10:36:25 -07004134 /* Now try it as a DSA key. */
4135 try {
4136 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08004137 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07004138 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07004139 Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07004140 } catch (InvalidKeySpecException e) {
4141 // Not a DSA public key.
4142 }
4143
dcashman1616f302015-05-29 14:47:23 -07004144 /* Not a supported key type */
Kenny Root05ca4c92011-09-15 10:36:25 -07004145 return null;
4146 }
4147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004148 private static final String ANDROID_RESOURCES
4149 = "http://schemas.android.com/apk/res/android";
4150
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004151 private boolean parseIntent(Resources res, XmlPullParser parser, AttributeSet attrs,
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08004152 boolean allowGlobs, boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004153 throws XmlPullParserException, IOException {
4154
4155 TypedArray sa = res.obtainAttributes(attrs,
4156 com.android.internal.R.styleable.AndroidManifestIntentFilter);
4157
4158 int priority = sa.getInt(
4159 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004160 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08004161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004162 TypedValue v = sa.peekValue(
4163 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
4164 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4165 outInfo.nonLocalizedLabel = v.coerceToString();
4166 }
4167
4168 outInfo.icon = sa.getResourceId(
4169 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
Adam Powell81cd2e92010-04-21 16:35:18 -07004170
4171 outInfo.logo = sa.getResourceId(
4172 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173
Jose Limaf78e3122014-03-06 12:13:15 -08004174 outInfo.banner = sa.getResourceId(
4175 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
4176
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08004177 if (allowAutoVerify) {
4178 outInfo.setAutoVerify(sa.getBoolean(
4179 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
4180 false));
4181 }
4182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004183 sa.recycle();
4184
4185 int outerDepth = parser.getDepth();
4186 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07004187 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
4188 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
4189 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004190 continue;
4191 }
4192
4193 String nodeName = parser.getName();
4194 if (nodeName.equals("action")) {
4195 String value = attrs.getAttributeValue(
4196 ANDROID_RESOURCES, "name");
4197 if (value == null || value == "") {
4198 outError[0] = "No value supplied for <android:name>";
4199 return false;
4200 }
4201 XmlUtils.skipCurrentTag(parser);
4202
4203 outInfo.addAction(value);
4204 } else if (nodeName.equals("category")) {
4205 String value = attrs.getAttributeValue(
4206 ANDROID_RESOURCES, "name");
4207 if (value == null || value == "") {
4208 outError[0] = "No value supplied for <android:name>";
4209 return false;
4210 }
4211 XmlUtils.skipCurrentTag(parser);
4212
4213 outInfo.addCategory(value);
4214
4215 } else if (nodeName.equals("data")) {
4216 sa = res.obtainAttributes(attrs,
4217 com.android.internal.R.styleable.AndroidManifestData);
4218
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004219 String str = sa.getNonConfigurationString(
4220 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004221 if (str != null) {
4222 try {
4223 outInfo.addDataType(str);
4224 } catch (IntentFilter.MalformedMimeTypeException e) {
4225 outError[0] = e.toString();
4226 sa.recycle();
4227 return false;
4228 }
4229 }
4230
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004231 str = sa.getNonConfigurationString(
4232 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004233 if (str != null) {
4234 outInfo.addDataScheme(str);
4235 }
4236
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07004237 str = sa.getNonConfigurationString(
4238 com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
4239 if (str != null) {
4240 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
4241 }
4242
4243 str = sa.getNonConfigurationString(
4244 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
4245 if (str != null) {
4246 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
4247 }
4248
4249 str = sa.getNonConfigurationString(
4250 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
4251 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004252 if (!allowGlobs) {
4253 outError[0] = "sspPattern not allowed here; ssp must be literal";
4254 return false;
4255 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07004256 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4257 }
4258
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004259 String host = sa.getNonConfigurationString(
4260 com.android.internal.R.styleable.AndroidManifestData_host, 0);
4261 String port = sa.getNonConfigurationString(
4262 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004263 if (host != null) {
4264 outInfo.addDataAuthority(host, port);
4265 }
4266
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004267 str = sa.getNonConfigurationString(
4268 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004269 if (str != null) {
4270 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
4271 }
4272
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004273 str = sa.getNonConfigurationString(
4274 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004275 if (str != null) {
4276 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
4277 }
4278
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004279 str = sa.getNonConfigurationString(
4280 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004281 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004282 if (!allowGlobs) {
4283 outError[0] = "pathPattern not allowed here; path must be literal";
4284 return false;
4285 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004286 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4287 }
4288
4289 sa.recycle();
4290 XmlUtils.skipCurrentTag(parser);
4291 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004292 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004293 + parser.getName() + " at " + mArchiveSourcePath + " "
4294 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004295 XmlUtils.skipCurrentTag(parser);
4296 } else {
4297 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
4298 return false;
4299 }
4300 }
4301
4302 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07004303
4304 if (DEBUG_PARSER) {
4305 final StringBuilder cats = new StringBuilder("Intent d=");
4306 cats.append(outInfo.hasDefault);
4307 cats.append(", cat=");
4308
4309 final Iterator<String> it = outInfo.categoriesIterator();
4310 if (it != null) {
4311 while (it.hasNext()) {
4312 cats.append(' ');
4313 cats.append(it.next());
4314 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004315 }
Kenny Rootd2d29252011-08-08 11:27:57 -07004316 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004317 }
4318
4319 return true;
4320 }
4321
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004322 /**
4323 * Representation of a full package parsed from APK files on disk. A package
4324 * consists of a single base APK, and zero or more split APKs.
4325 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004326 public final static class Package {
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07004327
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004328 public String packageName;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004329
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004330 /** Names of any split APKs, ordered by parsed splitName */
4331 public String[] splitNames;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004332
4333 // TODO: work towards making these paths invariant
Jeff Sharkey275e0852014-06-17 18:18:49 -07004334
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07004335 public String volumeUuid;
4336
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004337 /**
4338 * Path where this package was found on disk. For monolithic packages
4339 * this is path to single base APK file; for cluster packages this is
4340 * path to the cluster directory.
4341 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004342 public String codePath;
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004343
4344 /** Path of base APK */
4345 public String baseCodePath;
4346 /** Paths of any split APKs, ordered by parsed splitName */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004347 public String[] splitCodePaths;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004348
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004349 /** Revision code of base APK */
4350 public int baseRevisionCode;
4351 /** Revision codes of any split APKs, ordered by parsed splitName */
4352 public int[] splitRevisionCodes;
4353
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004354 /** Flags of any split APKs; ordered by parsed splitName */
4355 public int[] splitFlags;
4356
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004357 /**
4358 * Private flags of any split APKs; ordered by parsed splitName.
4359 *
4360 * {@hide}
4361 */
4362 public int[] splitPrivateFlags;
4363
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004364 public boolean baseHardwareAccelerated;
4365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004366 // For now we only support one application per package.
4367 public final ApplicationInfo applicationInfo = new ApplicationInfo();
4368
4369 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
4370 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
4371 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
4372 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
4373 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
4374 public final ArrayList<Service> services = new ArrayList<Service>(0);
4375 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
4376
4377 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
4378
Dianne Hackborn854060af2009-07-09 18:14:31 -07004379 public ArrayList<String> protectedBroadcasts;
Dianne Hackbornc895be72013-03-11 17:48:43 -07004380
4381 public ArrayList<String> libraryNames = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07004382 public ArrayList<String> usesLibraries = null;
4383 public ArrayList<String> usesOptionalLibraries = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004384 public String[] usesLibraryFiles = null;
4385
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004386 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
4387
Dianne Hackbornc1552392010-03-03 16:19:01 -08004388 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004389 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08004390 public ArrayList<String> mAdoptPermissions = null;
4391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004392 // We store the application meta-data independently to avoid multiple unwanted references
4393 public Bundle mAppMetaData = null;
4394
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004395 // The version code declared for this package.
4396 public int mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004398 // The version name declared for this package.
4399 public String mVersionName;
4400
4401 // The shared user id that this package wants to use.
4402 public String mSharedUserId;
4403
4404 // The shared user label that this package wants to use.
4405 public int mSharedUserLabel;
4406
4407 // Signatures that were read from the package.
Jeff Sharkey275e0852014-06-17 18:18:49 -07004408 public Signature[] mSignatures;
4409 public Certificate[][] mCertificates;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004410
4411 // For use by package manager service for quick lookup of
4412 // preferred up order.
4413 public int mPreferredOrder = 0;
4414
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07004415 // For use by package manager to keep track of where it needs to do dexopt.
Narayan Kamath20531682014-07-14 13:18:43 +01004416 public final ArraySet<String> mDexOptPerformed = new ArraySet<>(4);
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07004417
4418 // For use by package manager to keep track of when a package was last used.
4419 public long mLastPackageUsageTimeInMills;
4420
Amith Yamasani13593602012-03-22 16:16:17 -07004421 // // User set enabled state.
4422 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
4423 //
4424 // // Whether the package has been stopped.
4425 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004427 // Additional data supplied by callers.
4428 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07004429
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004430 // Applications hardware preferences
4431 public ArrayList<ConfigurationInfo> configPreferences = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004432
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004433 // Applications requested features
Dianne Hackborn49237342009-08-27 20:08:01 -07004434 public ArrayList<FeatureInfo> reqFeatures = null;
4435
Adam Lesinskid3edfde2014-08-08 17:32:44 -07004436 // Applications requested feature groups
4437 public ArrayList<FeatureGroupInfo> featureGroups = null;
4438
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08004439 public int installLocation;
4440
Jeff Hao272bf3a2014-10-08 13:34:43 -07004441 public boolean coreApp;
4442
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08004443 /* An app that's required for all users and cannot be uninstalled for a user */
4444 public boolean mRequiredForAllUsers;
4445
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07004446 /* The restricted account authenticator type that is used by this application */
4447 public String mRestrictedAccountType;
4448
Amith Yamasaniccbe3892013-04-12 17:52:42 -07004449 /* The required account type without which this application will not function */
4450 public String mRequiredAccountType;
4451
Kenny Rootbcc954d2011-08-08 16:19:08 -07004452 /**
4453 * Digest suitable for comparing whether this package's manifest is the
4454 * same as another.
4455 */
4456 public ManifestDigest manifestDigest;
4457
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01004458 public String mOverlayTarget;
4459 public int mOverlayPriority;
4460 public boolean mTrustedOverlay;
4461
Geremy Condraf1bcca82013-01-07 22:35:24 -08004462 /**
dcashman989eb3712014-06-17 12:56:12 -07004463 * Data used to feed the KeySetManagerService
Geremy Condraf1bcca82013-01-07 22:35:24 -08004464 */
dcashman989eb3712014-06-17 12:56:12 -07004465 public ArraySet<PublicKey> mSigningKeys;
4466 public ArraySet<String> mUpgradeKeySets;
4467 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -08004468
Narayan Kamath4903f642014-08-11 13:33:45 +01004469 /**
4470 * The install time abi override for this package, if any.
4471 *
4472 * TODO: This seems like a horrible place to put the abiOverride because
4473 * this isn't something the packageParser parsers. However, this fits in with
4474 * the rest of the PackageManager where package scanning randomly pushes
4475 * and prods fields out of {@code this.applicationInfo}.
4476 */
4477 public String cpuAbiOverride;
4478
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004479 public Package(String packageName) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07004480 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07004481 applicationInfo.packageName = packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004482 applicationInfo.uid = -1;
4483 }
4484
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004485 public List<String> getAllCodePaths() {
Jeff Sharkey275e0852014-06-17 18:18:49 -07004486 ArrayList<String> paths = new ArrayList<>();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004487 paths.add(baseCodePath);
Jeff Sharkey275e0852014-06-17 18:18:49 -07004488 if (!ArrayUtils.isEmpty(splitCodePaths)) {
4489 Collections.addAll(paths, splitCodePaths);
4490 }
4491 return paths;
4492 }
4493
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004494 /**
4495 * Filtered set of {@link #getAllCodePaths()} that excludes
4496 * resource-only APKs.
4497 */
4498 public List<String> getAllCodePathsExcludingResourceOnly() {
4499 ArrayList<String> paths = new ArrayList<>();
4500 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
4501 paths.add(baseCodePath);
4502 }
4503 if (!ArrayUtils.isEmpty(splitCodePaths)) {
4504 for (int i = 0; i < splitCodePaths.length; i++) {
4505 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
4506 paths.add(splitCodePaths[i]);
4507 }
4508 }
4509 }
4510 return paths;
4511 }
4512
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004513 public void setPackageName(String newName) {
4514 packageName = newName;
4515 applicationInfo.packageName = newName;
4516 for (int i=permissions.size()-1; i>=0; i--) {
4517 permissions.get(i).setPackageName(newName);
4518 }
4519 for (int i=permissionGroups.size()-1; i>=0; i--) {
4520 permissionGroups.get(i).setPackageName(newName);
4521 }
4522 for (int i=activities.size()-1; i>=0; i--) {
4523 activities.get(i).setPackageName(newName);
4524 }
4525 for (int i=receivers.size()-1; i>=0; i--) {
4526 receivers.get(i).setPackageName(newName);
4527 }
4528 for (int i=providers.size()-1; i>=0; i--) {
4529 providers.get(i).setPackageName(newName);
4530 }
4531 for (int i=services.size()-1; i>=0; i--) {
4532 services.get(i).setPackageName(newName);
4533 }
4534 for (int i=instrumentation.size()-1; i>=0; i--) {
4535 instrumentation.get(i).setPackageName(newName);
4536 }
4537 }
Dianne Hackborn65696252012-03-05 18:49:21 -08004538
4539 public boolean hasComponentClassName(String name) {
4540 for (int i=activities.size()-1; i>=0; i--) {
4541 if (name.equals(activities.get(i).className)) {
4542 return true;
4543 }
4544 }
4545 for (int i=receivers.size()-1; i>=0; i--) {
4546 if (name.equals(receivers.get(i).className)) {
4547 return true;
4548 }
4549 }
4550 for (int i=providers.size()-1; i>=0; i--) {
4551 if (name.equals(providers.get(i).className)) {
4552 return true;
4553 }
4554 }
4555 for (int i=services.size()-1; i>=0; i--) {
4556 if (name.equals(services.get(i).className)) {
4557 return true;
4558 }
4559 }
4560 for (int i=instrumentation.size()-1; i>=0; i--) {
4561 if (name.equals(instrumentation.get(i).className)) {
4562 return true;
4563 }
4564 }
4565 return false;
4566 }
4567
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08004568 /**
4569 * @hide
4570 */
4571 public boolean isForwardLocked() {
4572 return applicationInfo.isForwardLocked();
4573 }
4574
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08004575 /**
4576 * @hide
4577 */
4578 public boolean isSystemApp() {
4579 return applicationInfo.isSystemApp();
4580 }
4581
4582 /**
4583 * @hide
4584 */
Svet Ganovadc1cf42015-06-15 16:36:24 -07004585 public boolean isPrivilegedApp() {
4586 return applicationInfo.isPrivilegedApp();
4587 }
4588
4589 /**
4590 * @hide
4591 */
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08004592 public boolean isUpdatedSystemApp() {
4593 return applicationInfo.isUpdatedSystemApp();
4594 }
4595
Fyodor Kupolovebcac162015-09-09 15:56:45 -07004596 /**
4597 * @hide
4598 */
4599 public boolean canHaveOatDir() {
4600 // The following app types CANNOT have oat directory
4601 // - non-updated system apps
4602 // - forward-locked apps or apps installed in ASEC containers
4603 return (!isSystemApp() || isUpdatedSystemApp())
4604 && !isForwardLocked() && !applicationInfo.isExternalAsec();
4605 }
4606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004607 public String toString() {
4608 return "Package{"
4609 + Integer.toHexString(System.identityHashCode(this))
4610 + " " + packageName + "}";
4611 }
4612 }
4613
4614 public static class Component<II extends IntentInfo> {
4615 public final Package owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004616 public final ArrayList<II> intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004617 public final String className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004618 public Bundle metaData;
4619
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004620 ComponentName componentName;
4621 String componentShortName;
4622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004623 public Component(Package _owner) {
4624 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004625 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004626 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004627 }
4628
4629 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
4630 owner = args.owner;
4631 intents = new ArrayList<II>(0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004632 String name = args.sa.getNonConfigurationString(args.nameRes, 0);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004633 if (name == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004634 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004635 args.outError[0] = args.tag + " does not specify android:name";
4636 return;
4637 }
4638
4639 outInfo.name
4640 = buildClassName(owner.applicationInfo.packageName, name, args.outError);
4641 if (outInfo.name == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004642 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004643 args.outError[0] = args.tag + " does not have valid android:name";
4644 return;
4645 }
4646
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004647 className = outInfo.name;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004648
4649 int iconVal = args.sa.getResourceId(args.iconRes, 0);
4650 if (iconVal != 0) {
4651 outInfo.icon = iconVal;
4652 outInfo.nonLocalizedLabel = null;
4653 }
Adam Powell81cd2e92010-04-21 16:35:18 -07004654
4655 int logoVal = args.sa.getResourceId(args.logoRes, 0);
4656 if (logoVal != 0) {
4657 outInfo.logo = logoVal;
4658 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004659
Jose Limaf78e3122014-03-06 12:13:15 -08004660 int bannerVal = args.sa.getResourceId(args.bannerRes, 0);
4661 if (bannerVal != 0) {
4662 outInfo.banner = bannerVal;
4663 }
4664
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004665 TypedValue v = args.sa.peekValue(args.labelRes);
4666 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4667 outInfo.nonLocalizedLabel = v.coerceToString();
4668 }
4669
4670 outInfo.packageName = owner.packageName;
4671 }
4672
4673 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
4674 this(args, (PackageItemInfo)outInfo);
4675 if (args.outError[0] != null) {
4676 return;
4677 }
4678
4679 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07004680 CharSequence pname;
4681 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004682 pname = args.sa.getNonConfigurationString(args.processRes,
4683 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07004684 } else {
4685 // Some older apps have been seen to use a resource reference
4686 // here that on older builds was ignored (with a warning). We
4687 // need to continue to do this for them so they don't break.
4688 pname = args.sa.getNonResourceString(args.processRes);
4689 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004690 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07004691 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004692 args.flags, args.sepProcesses, args.outError);
4693 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004694
4695 if (args.descriptionRes != 0) {
4696 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
4697 }
4698
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004699 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004700 }
4701
4702 public Component(Component<II> clone) {
4703 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004704 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004705 className = clone.className;
4706 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004707 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004708 }
4709
4710 public ComponentName getComponentName() {
4711 if (componentName != null) {
4712 return componentName;
4713 }
4714 if (className != null) {
4715 componentName = new ComponentName(owner.applicationInfo.packageName,
4716 className);
4717 }
4718 return componentName;
4719 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07004720
4721 public void appendComponentShortName(StringBuilder sb) {
4722 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004723 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07004724
4725 public void printComponentShortName(PrintWriter pw) {
4726 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
4727 }
4728
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004729 public void setPackageName(String packageName) {
4730 componentName = null;
4731 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004732 }
4733 }
4734
4735 public final static class Permission extends Component<IntentInfo> {
4736 public final PermissionInfo info;
4737 public boolean tree;
4738 public PermissionGroup group;
4739
4740 public Permission(Package _owner) {
4741 super(_owner);
4742 info = new PermissionInfo();
4743 }
4744
4745 public Permission(Package _owner, PermissionInfo _info) {
4746 super(_owner);
4747 info = _info;
4748 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004749
4750 public void setPackageName(String packageName) {
4751 super.setPackageName(packageName);
4752 info.packageName = packageName;
4753 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004754
4755 public String toString() {
4756 return "Permission{"
4757 + Integer.toHexString(System.identityHashCode(this))
4758 + " " + info.name + "}";
4759 }
4760 }
4761
4762 public final static class PermissionGroup extends Component<IntentInfo> {
4763 public final PermissionGroupInfo info;
4764
4765 public PermissionGroup(Package _owner) {
4766 super(_owner);
4767 info = new PermissionGroupInfo();
4768 }
4769
4770 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
4771 super(_owner);
4772 info = _info;
4773 }
4774
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004775 public void setPackageName(String packageName) {
4776 super.setPackageName(packageName);
4777 info.packageName = packageName;
4778 }
4779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780 public String toString() {
4781 return "PermissionGroup{"
4782 + Integer.toHexString(System.identityHashCode(this))
4783 + " " + info.name + "}";
4784 }
4785 }
4786
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004787 private static boolean copyNeeded(int flags, Package p,
4788 PackageUserState state, Bundle metaData, int userId) {
Xiaohui Chen98404fd2015-08-17 16:09:02 -07004789 if (userId != UserHandle.USER_SYSTEM) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004790 // We always need to copy for other users, since we need
4791 // to fix up the uid.
4792 return true;
4793 }
4794 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
4795 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07004796 if (p.applicationInfo.enabled != enabled) {
4797 return true;
4798 }
4799 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004800 if (!state.installed || state.hidden) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004801 return true;
4802 }
4803 if (state.stopped) {
4804 return true;
4805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004806 if ((flags & PackageManager.GET_META_DATA) != 0
4807 && (metaData != null || p.mAppMetaData != null)) {
4808 return true;
4809 }
4810 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
4811 && p.usesLibraryFiles != null) {
4812 return true;
4813 }
4814 return false;
4815 }
4816
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004817 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
4818 PackageUserState state) {
4819 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07004820 }
4821
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08004822 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
4823 PackageUserState state) {
4824 // CompatibilityMode is global state.
4825 if (!sCompatibilityModeEnabled) {
4826 ai.disableCompatibilityMode();
4827 }
4828 if (state.installed) {
4829 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
4830 } else {
4831 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
4832 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004833 if (state.hidden) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004834 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07004835 } else {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004836 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07004837 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08004838 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
4839 ai.enabled = true;
4840 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
4841 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
4842 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
4843 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
4844 ai.enabled = false;
4845 }
4846 ai.enabledSetting = state.enabled;
4847 }
4848
Amith Yamasani13593602012-03-22 16:16:17 -07004849 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004850 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004851 if (p == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004852 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004853 return null;
4854 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08004855 if (!copyNeeded(flags, p, state, null, userId)
4856 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
4857 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
4858 // In this case it is safe to directly modify the internal ApplicationInfo state:
4859 // - CompatibilityMode is global state, so will be the same for every call.
4860 // - We only come in to here if the app should reported as installed; this is the
4861 // default state, and we will do a copy otherwise.
4862 // - The enable state will always be reported the same for the application across
4863 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
4864 // be doing a copy.
4865 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004866 return p.applicationInfo;
4867 }
4868
4869 // Make shallow copy so we can store the metadata/libraries safely
4870 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Amith Yamasani1742cfb2015-04-14 15:41:20 -07004871 ai.uid = UserHandle.getUid(userId, ai.uid);
Jeff Sharkey6dce4962015-07-03 18:08:41 -07004872 ai.dataDir = Environment.getDataUserPackageDirectory(ai.volumeUuid, userId, ai.packageName)
Amith Yamasani1742cfb2015-04-14 15:41:20 -07004873 .getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004874 if ((flags & PackageManager.GET_META_DATA) != 0) {
4875 ai.metaData = p.mAppMetaData;
4876 }
4877 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
4878 ai.sharedLibraryFiles = p.usesLibraryFiles;
4879 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004880 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07004881 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004882 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07004883 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004884 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08004885 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004886 return ai;
4887 }
4888
Dianne Hackbornace27912014-09-18 18:38:30 -07004889 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
4890 PackageUserState state, int userId) {
4891 if (ai == null) return null;
4892 if (!checkUseInstalledOrHidden(flags, state)) {
4893 return null;
4894 }
4895 // This is only used to return the ResolverActivity; we will just always
4896 // make a copy.
4897 ai = new ApplicationInfo(ai);
Amith Yamasani1742cfb2015-04-14 15:41:20 -07004898 ai.uid = UserHandle.getUid(userId, ai.uid);
Jeff Sharkey6dce4962015-07-03 18:08:41 -07004899 ai.dataDir = Environment.getDataUserPackageDirectory(ai.volumeUuid, userId, ai.packageName)
Amith Yamasani1742cfb2015-04-14 15:41:20 -07004900 .getAbsolutePath();
Dianne Hackbornace27912014-09-18 18:38:30 -07004901 if (state.stopped) {
4902 ai.flags |= ApplicationInfo.FLAG_STOPPED;
4903 } else {
4904 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
4905 }
4906 updateApplicationInfo(ai, flags, state);
4907 return ai;
4908 }
4909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004910 public static final PermissionInfo generatePermissionInfo(
4911 Permission p, int flags) {
4912 if (p == null) return null;
4913 if ((flags&PackageManager.GET_META_DATA) == 0) {
4914 return p.info;
4915 }
4916 PermissionInfo pi = new PermissionInfo(p.info);
4917 pi.metaData = p.metaData;
4918 return pi;
4919 }
4920
4921 public static final PermissionGroupInfo generatePermissionGroupInfo(
4922 PermissionGroup pg, int flags) {
4923 if (pg == null) return null;
4924 if ((flags&PackageManager.GET_META_DATA) == 0) {
4925 return pg.info;
4926 }
4927 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
4928 pgi.metaData = pg.metaData;
4929 return pgi;
4930 }
4931
4932 public final static class Activity extends Component<ActivityIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004933 public final ActivityInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004934
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004935 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
4936 super(args, _info);
4937 info = _info;
4938 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004940
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004941 public void setPackageName(String packageName) {
4942 super.setPackageName(packageName);
4943 info.packageName = packageName;
4944 }
4945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004946 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07004947 StringBuilder sb = new StringBuilder(128);
4948 sb.append("Activity{");
4949 sb.append(Integer.toHexString(System.identityHashCode(this)));
4950 sb.append(' ');
4951 appendComponentShortName(sb);
4952 sb.append('}');
4953 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004954 }
4955 }
4956
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004957 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
4958 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004959 if (a == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004960 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004961 return null;
4962 }
4963 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004964 return a.info;
4965 }
4966 // Make shallow copies so we can store the metadata safely
4967 ActivityInfo ai = new ActivityInfo(a.info);
4968 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004969 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004970 return ai;
4971 }
4972
Dianne Hackbornace27912014-09-18 18:38:30 -07004973 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
4974 PackageUserState state, int userId) {
4975 if (ai == null) return null;
4976 if (!checkUseInstalledOrHidden(flags, state)) {
4977 return null;
4978 }
4979 // This is only used to return the ResolverActivity; we will just always
4980 // make a copy.
4981 ai = new ActivityInfo(ai);
4982 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
4983 return ai;
4984 }
4985
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004986 public final static class Service extends Component<ServiceIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004987 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004988
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004989 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
4990 super(args, _info);
4991 info = _info;
4992 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004993 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004994
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004995 public void setPackageName(String packageName) {
4996 super.setPackageName(packageName);
4997 info.packageName = packageName;
4998 }
4999
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005000 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005001 StringBuilder sb = new StringBuilder(128);
5002 sb.append("Service{");
5003 sb.append(Integer.toHexString(System.identityHashCode(this)));
5004 sb.append(' ');
5005 appendComponentShortName(sb);
5006 sb.append('}');
5007 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005008 }
5009 }
5010
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005011 public static final ServiceInfo generateServiceInfo(Service s, int flags,
5012 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005013 if (s == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07005014 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005015 return null;
5016 }
5017 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005018 return s.info;
5019 }
5020 // Make shallow copies so we can store the metadata safely
5021 ServiceInfo si = new ServiceInfo(s.info);
5022 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005023 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005024 return si;
5025 }
5026
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005027 public final static class Provider extends Component<ProviderIntentInfo> {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005028 public final ProviderInfo info;
5029 public boolean syncable;
5030
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005031 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
5032 super(args, _info);
5033 info = _info;
5034 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005035 syncable = false;
5036 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005038 public Provider(Provider existingProvider) {
5039 super(existingProvider);
5040 this.info = existingProvider.info;
5041 this.syncable = existingProvider.syncable;
5042 }
5043
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005044 public void setPackageName(String packageName) {
5045 super.setPackageName(packageName);
5046 info.packageName = packageName;
5047 }
5048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005049 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005050 StringBuilder sb = new StringBuilder(128);
5051 sb.append("Provider{");
5052 sb.append(Integer.toHexString(System.identityHashCode(this)));
5053 sb.append(' ');
5054 appendComponentShortName(sb);
5055 sb.append('}');
5056 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005057 }
5058 }
5059
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005060 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
5061 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005062 if (p == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07005063 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005064 return null;
5065 }
5066 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005067 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005068 || p.info.uriPermissionPatterns == null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005069 return p.info;
5070 }
5071 // Make shallow copies so we can store the metadata safely
5072 ProviderInfo pi = new ProviderInfo(p.info);
5073 pi.metaData = p.metaData;
5074 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
5075 pi.uriPermissionPatterns = null;
5076 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005077 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005078 return pi;
5079 }
5080
5081 public final static class Instrumentation extends Component {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005082 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005083
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005084 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
5085 super(args, _info);
5086 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005087 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005088
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005089 public void setPackageName(String packageName) {
5090 super.setPackageName(packageName);
5091 info.packageName = packageName;
5092 }
5093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005094 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005095 StringBuilder sb = new StringBuilder(128);
5096 sb.append("Instrumentation{");
5097 sb.append(Integer.toHexString(System.identityHashCode(this)));
5098 sb.append(' ');
5099 appendComponentShortName(sb);
5100 sb.append('}');
5101 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005102 }
5103 }
5104
5105 public static final InstrumentationInfo generateInstrumentationInfo(
5106 Instrumentation i, int flags) {
5107 if (i == null) return null;
5108 if ((flags&PackageManager.GET_META_DATA) == 0) {
5109 return i.info;
5110 }
5111 InstrumentationInfo ii = new InstrumentationInfo(i.info);
5112 ii.metaData = i.metaData;
5113 return ii;
5114 }
5115
5116 public static class IntentInfo extends IntentFilter {
5117 public boolean hasDefault;
5118 public int labelRes;
5119 public CharSequence nonLocalizedLabel;
5120 public int icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07005121 public int logo;
Jose Limaf78e3122014-03-06 12:13:15 -08005122 public int banner;
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005123 public int preferred;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005124 }
5125
5126 public final static class ActivityIntentInfo extends IntentInfo {
5127 public final Activity activity;
5128
5129 public ActivityIntentInfo(Activity _activity) {
5130 activity = _activity;
5131 }
5132
5133 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005134 StringBuilder sb = new StringBuilder(128);
5135 sb.append("ActivityIntentInfo{");
5136 sb.append(Integer.toHexString(System.identityHashCode(this)));
5137 sb.append(' ');
5138 activity.appendComponentShortName(sb);
5139 sb.append('}');
5140 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005141 }
5142 }
5143
5144 public final static class ServiceIntentInfo extends IntentInfo {
5145 public final Service service;
5146
5147 public ServiceIntentInfo(Service _service) {
5148 service = _service;
5149 }
5150
5151 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005152 StringBuilder sb = new StringBuilder(128);
5153 sb.append("ServiceIntentInfo{");
5154 sb.append(Integer.toHexString(System.identityHashCode(this)));
5155 sb.append(' ');
5156 service.appendComponentShortName(sb);
5157 sb.append('}');
5158 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005159 }
5160 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005161
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005162 public static final class ProviderIntentInfo extends IntentInfo {
5163 public final Provider provider;
5164
5165 public ProviderIntentInfo(Provider provider) {
5166 this.provider = provider;
5167 }
5168
5169 public String toString() {
5170 StringBuilder sb = new StringBuilder(128);
5171 sb.append("ProviderIntentInfo{");
5172 sb.append(Integer.toHexString(System.identityHashCode(this)));
5173 sb.append(' ');
5174 provider.appendComponentShortName(sb);
5175 sb.append('}');
5176 return sb.toString();
5177 }
5178 }
5179
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005180 /**
5181 * @hide
5182 */
5183 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
5184 sCompatibilityModeEnabled = compatibilityModeEnabled;
5185 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005186
Jeff Sharkey275e0852014-06-17 18:18:49 -07005187 private static AtomicReference<byte[]> sBuffer = new AtomicReference<byte[]>();
5188
5189 public static long readFullyIgnoringContents(InputStream in) throws IOException {
5190 byte[] buffer = sBuffer.getAndSet(null);
5191 if (buffer == null) {
5192 buffer = new byte[4096];
5193 }
5194
5195 int n = 0;
5196 int count = 0;
5197 while ((n = in.read(buffer, 0, buffer.length)) != -1) {
5198 count += n;
5199 }
5200
5201 sBuffer.set(buffer);
5202 return count;
5203 }
5204
5205 public static void closeQuietly(StrictJarFile jarFile) {
5206 if (jarFile != null) {
5207 try {
5208 jarFile.close();
5209 } catch (Exception ignored) {
5210 }
5211 }
5212 }
5213
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005214 public static class PackageParserException extends Exception {
5215 public final int error;
5216
5217 public PackageParserException(int error, String detailMessage) {
5218 super(detailMessage);
5219 this.error = error;
5220 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07005221
5222 public PackageParserException(int error, String detailMessage, Throwable throwable) {
5223 super(detailMessage, throwable);
5224 this.error = error;
5225 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005226 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005227}