blob: 40f4e8f90b9674a485a5f8cc1c640b9d209995b9 [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;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070027
Dianne Hackborn852975d2014-08-22 17:42:43 -070028import android.app.ActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.content.ComponentName;
30import android.content.Intent;
31import android.content.IntentFilter;
32import android.content.res.AssetManager;
33import android.content.res.Configuration;
34import android.content.res.Resources;
35import android.content.res.TypedArray;
36import android.content.res.XmlResourceParser;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -070037import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.os.Bundle;
39import android.os.PatternMatcher;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070040import android.os.UserHandle;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -070041import android.text.TextUtils;
Jeff Sharkey275e0852014-06-17 18:18:49 -070042import android.util.ArrayMap;
43import android.util.ArraySet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.util.AttributeSet;
Kenny Root05ca4c92011-09-15 10:36:25 -070045import android.util.Base64;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.util.DisplayMetrics;
Kenny Root05ca4c92011-09-15 10:36:25 -070047import android.util.Log;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070048import android.util.Pair;
Kenny Rootd2d29252011-08-08 11:27:57 -070049import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.util.TypedValue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -080052import com.android.internal.R;
Jeff Sharkey275e0852014-06-17 18:18:49 -070053import com.android.internal.util.ArrayUtils;
54import com.android.internal.util.XmlUtils;
55
56import libcore.io.IoUtils;
57
58import org.xmlpull.v1.XmlPullParser;
59import org.xmlpull.v1.XmlPullParserException;
60
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import java.io.File;
62import java.io.IOException;
63import java.io.InputStream;
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -070064import java.io.PrintWriter;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070065import java.security.GeneralSecurityException;
Kenny Root05ca4c92011-09-15 10:36:25 -070066import java.security.KeyFactory;
67import java.security.NoSuchAlgorithmException;
68import java.security.PublicKey;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import java.security.cert.Certificate;
70import java.security.cert.CertificateEncodingException;
Kenny Root05ca4c92011-09-15 10:36:25 -070071import java.security.spec.EncodedKeySpec;
72import java.security.spec.InvalidKeySpecException;
73import java.security.spec.X509EncodedKeySpec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074import java.util.ArrayList;
Dianne Hackbornffcda102014-04-24 13:06:27 -070075import java.util.Arrays;
Jeff Sharkey275e0852014-06-17 18:18:49 -070076import java.util.Collections;
77import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078import java.util.Iterator;
Kenny Root05ca4c92011-09-15 10:36:25 -070079import java.util.List;
Geremy Condraf1bcca82013-01-07 22:35:24 -080080import java.util.Set;
Jeff Sharkey275e0852014-06-17 18:18:49 -070081import java.util.concurrent.atomic.AtomicReference;
Narayan Kamatheb565dc2013-12-12 16:54:33 +000082import java.util.jar.StrictJarFile;
Kenny Root6c918ce2013-04-02 14:04:24 -070083import java.util.zip.ZipEntry;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084
85/**
Jeff Sharkeyda96e132014-07-15 14:54:09 -070086 * Parser for package files (APKs) on disk. This supports apps packaged either
87 * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
88 * APKs in a single directory.
89 * <p>
90 * Apps packaged as multiple APKs always consist of a single "base" APK (with a
91 * {@code null} split name) and zero or more "split" APKs (with unique split
92 * names). Any subset of those split APKs are a valid install, as long as the
93 * following constraints are met:
94 * <ul>
95 * <li>All APKs must have the exact same package name, version code, and signing
96 * certificates.
97 * <li>All APKs must have unique split names.
98 * <li>All installations must contain a single base APK.
99 * </ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700101 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 */
103public class PackageParser {
Kenny Rootd2d29252011-08-08 11:27:57 -0700104 private static final boolean DEBUG_JAR = false;
105 private static final boolean DEBUG_PARSER = false;
106 private static final boolean DEBUG_BACKUP = false;
107
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700108 // TODO: switch outError users to PackageParserException
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700109 // TODO: refactor "codePath" to "apkPath"
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700110
Kenny Rootbcc954d2011-08-08 16:19:08 -0700111 /** File name in an APK for the Android manifest. */
112 private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
113
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700114 /** Path prefix for apps on expanded storage */
115 private static final String MNT_EXPAND = "/mnt/expand/";
116
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700117 /** @hide */
118 public static class NewPermissionInfo {
119 public final String name;
120 public final int sdkVersion;
121 public final int fileVersion;
122
123 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
124 this.name = name;
125 this.sdkVersion = sdkVersion;
126 this.fileVersion = fileVersion;
127 }
128 }
Dianne Hackborn79245122012-03-12 10:51:26 -0700129
130 /** @hide */
131 public static class SplitPermissionInfo {
132 public final String rootPerm;
133 public final String[] newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700134 public final int targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700135
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700136 public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
Dianne Hackborn79245122012-03-12 10:51:26 -0700137 this.rootPerm = rootPerm;
138 this.newPerms = newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700139 this.targetSdk = targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700140 }
141 }
142
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700143 /**
144 * List of new permissions that have been added since 1.0.
145 * NOTE: These must be declared in SDK version order, with permissions
146 * added to older SDKs appearing before those added to newer SDKs.
Dianne Hackborn79245122012-03-12 10:51:26 -0700147 * If sdkVersion is 0, then this is not a permission that we want to
148 * automatically add to older apps, but we do want to allow it to be
149 * granted during a platform update.
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700150 * @hide
151 */
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700152 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
153 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -0700154 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700155 android.os.Build.VERSION_CODES.DONUT, 0),
156 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
157 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700158 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159
Dianne Hackborn79245122012-03-12 10:51:26 -0700160 /**
161 * List of permissions that have been split into more granular or dependent
162 * permissions.
163 * @hide
164 */
165 public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
166 new PackageParser.SplitPermissionInfo[] {
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700167 // READ_EXTERNAL_STORAGE is always required when an app requests
168 // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
169 // write access without read access. The hack here with the target
170 // target SDK version ensures that this grant is always done.
Dianne Hackborn79245122012-03-12 10:51:26 -0700171 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700172 new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700173 android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700174 new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
175 new String[] { android.Manifest.permission.READ_CALL_LOG },
176 android.os.Build.VERSION_CODES.JELLY_BEAN),
177 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
178 new String[] { android.Manifest.permission.WRITE_CALL_LOG },
179 android.os.Build.VERSION_CODES.JELLY_BEAN)
Dianne Hackborn79245122012-03-12 10:51:26 -0700180 };
181
Jeff Sharkey275e0852014-06-17 18:18:49 -0700182 /**
183 * @deprecated callers should move to explicitly passing around source path.
184 */
185 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 private String mArchiveSourcePath;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700189 private boolean mOnlyCoreApps;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700190 private DisplayMetrics mMetrics;
191
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700192 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700193 private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194
195 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
196
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700197 private static boolean sCompatibilityModeEnabled = true;
Amith Yamasani655d0e22013-06-12 14:19:10 -0700198 private static final int PARSE_DEFAULT_INSTALL_LOCATION =
199 PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700200
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700201 static class ParsePackageItemArgs {
202 final Package owner;
203 final String[] outError;
204 final int nameRes;
205 final int labelRes;
206 final int iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700207 final int logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800208 final int bannerRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700209
210 String tag;
211 TypedArray sa;
212
213 ParsePackageItemArgs(Package _owner, String[] _outError,
Jose Limaf78e3122014-03-06 12:13:15 -0800214 int _nameRes, int _labelRes, int _iconRes, int _logoRes, int _bannerRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700215 owner = _owner;
216 outError = _outError;
217 nameRes = _nameRes;
218 labelRes = _labelRes;
219 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700220 logoRes = _logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800221 bannerRes = _bannerRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700222 }
223 }
224
225 static class ParseComponentArgs extends ParsePackageItemArgs {
226 final String[] sepProcesses;
227 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800228 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700229 final int enabledRes;
230 int flags;
231
232 ParseComponentArgs(Package _owner, String[] _outError,
Jose Limaf78e3122014-03-06 12:13:15 -0800233 int _nameRes, int _labelRes, int _iconRes, int _logoRes, int _bannerRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800234 String[] _sepProcesses, int _processRes,
235 int _descriptionRes, int _enabledRes) {
Jose Limaf78e3122014-03-06 12:13:15 -0800236 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _logoRes, _bannerRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700237 sepProcesses = _sepProcesses;
238 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800239 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700240 enabledRes = _enabledRes;
241 }
242 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800243
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700244 /**
Jeff Sharkey73767b92014-07-04 20:18:13 -0700245 * Lightweight parsed details about a single package.
246 */
247 public static class PackageLite {
248 public final String packageName;
249 public final int versionCode;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700250 public final int installLocation;
251 public final VerifierInfo[] verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700252
253 /** Names of any split APKs, ordered by parsed splitName */
254 public final String[] splitNames;
255
256 /**
257 * Path where this package was found on disk. For monolithic packages
258 * this is path to single base APK file; for cluster packages this is
259 * path to the cluster directory.
260 */
261 public final String codePath;
262
263 /** Path of base APK */
264 public final String baseCodePath;
265 /** Paths of any split APKs, ordered by parsed splitName */
266 public final String[] splitCodePaths;
267
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800268 /** Revision code of base APK */
269 public final int baseRevisionCode;
270 /** Revision codes of any split APKs, ordered by parsed splitName */
271 public final int[] splitRevisionCodes;
272
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700273 public final boolean coreApp;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100274 public final boolean multiArch;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700275 public final boolean extractNativeLibs;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100276
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700277 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800278 String[] splitCodePaths, int[] splitRevisionCodes) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700279 this.packageName = baseApk.packageName;
280 this.versionCode = baseApk.versionCode;
281 this.installLocation = baseApk.installLocation;
282 this.verifiers = baseApk.verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700283 this.splitNames = splitNames;
284 this.codePath = codePath;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700285 this.baseCodePath = baseApk.codePath;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700286 this.splitCodePaths = splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800287 this.baseRevisionCode = baseApk.revisionCode;
288 this.splitRevisionCodes = splitRevisionCodes;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700289 this.coreApp = baseApk.coreApp;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100290 this.multiArch = baseApk.multiArch;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700291 this.extractNativeLibs = baseApk.extractNativeLibs;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700292 }
293
294 public List<String> getAllCodePaths() {
295 ArrayList<String> paths = new ArrayList<>();
296 paths.add(baseCodePath);
297 if (!ArrayUtils.isEmpty(splitCodePaths)) {
298 Collections.addAll(paths, splitCodePaths);
299 }
300 return paths;
301 }
302 }
303
304 /**
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700305 * Lightweight parsed details about a single APK file.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800306 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700307 public static class ApkLite {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700308 public final String codePath;
Kenny Root05ca4c92011-09-15 10:36:25 -0700309 public final String packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700310 public final String splitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700311 public final int versionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800312 public final int revisionCode;
Kenny Root05ca4c92011-09-15 10:36:25 -0700313 public final int installLocation;
314 public final VerifierInfo[] verifiers;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700315 public final Signature[] signatures;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700316 public final boolean coreApp;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100317 public final boolean multiArch;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700318 public final boolean extractNativeLibs;
Kenny Root05ca4c92011-09-15 10:36:25 -0700319
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700320 public ApkLite(String codePath, String packageName, String splitName, int versionCode,
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800321 int revisionCode, int installLocation, List<VerifierInfo> verifiers,
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700322 Signature[] signatures, boolean coreApp, boolean multiArch,
323 boolean extractNativeLibs) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700324 this.codePath = codePath;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800325 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700326 this.splitName = splitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700327 this.versionCode = versionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800328 this.revisionCode = revisionCode;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800329 this.installLocation = installLocation;
Kenny Root05ca4c92011-09-15 10:36:25 -0700330 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700331 this.signatures = signatures;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700332 this.coreApp = coreApp;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100333 this.multiArch = multiArch;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700334 this.extractNativeLibs = extractNativeLibs;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800335 }
336 }
337
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700338 private ParsePackageItemArgs mParseInstrumentationArgs;
339 private ParseComponentArgs mParseActivityArgs;
340 private ParseComponentArgs mParseActivityAliasArgs;
341 private ParseComponentArgs mParseServiceArgs;
342 private ParseComponentArgs mParseProviderArgs;
343
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 /** If set to true, we will only allow package files that exactly match
345 * the DTD. Otherwise, we try to get as much from the package as we
346 * can without failing. This should normally be set to false, to
347 * support extensions to the DTD in future versions. */
348 private static final boolean RIGID_PARSER = false;
349
350 private static final String TAG = "PackageParser";
351
Jeff Sharkey275e0852014-06-17 18:18:49 -0700352 public PackageParser() {
353 mMetrics = new DisplayMetrics();
354 mMetrics.setToDefaults();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700355 }
356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357 public void setSeparateProcesses(String[] procs) {
358 mSeparateProcesses = procs;
359 }
360
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700361 /**
362 * Flag indicating this parser should only consider apps with
363 * {@code coreApp} manifest attribute to be valid apps. This is useful when
364 * creating a minimalist boot environment.
365 */
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700366 public void setOnlyCoreApps(boolean onlyCoreApps) {
367 mOnlyCoreApps = onlyCoreApps;
368 }
369
Jeff Sharkey275e0852014-06-17 18:18:49 -0700370 public void setDisplayMetrics(DisplayMetrics metrics) {
371 mMetrics = metrics;
372 }
373
Jeff Sharkey73767b92014-07-04 20:18:13 -0700374 public static final boolean isApkFile(File file) {
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700375 return isApkPath(file.getName());
376 }
377
378 private static boolean isApkPath(String path) {
379 return path.endsWith(".apk");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800380 }
381
382 /**
383 * Generate and return the {@link PackageInfo} for a parsed package.
384 *
385 * @param p the parsed package.
386 * @param flags indicating which optional information is included.
387 */
388 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Dianne Hackborne639da72012-02-21 15:11:13 -0800389 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svet Ganov3695b8a2015-03-24 16:30:25 -0700390 Set<String> grantedPermissions, PackageUserState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391
Amith Yamasani483f3b02012-03-13 16:08:00 -0700392 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700393 grantedPermissions, state, UserHandle.getCallingUserId());
394 }
395
Amith Yamasani655d0e22013-06-12 14:19:10 -0700396 /**
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700397 * Returns true if the package is installed and not hidden, or if the caller
398 * explicitly wanted all uninstalled and hidden packages as well.
Amith Yamasani655d0e22013-06-12 14:19:10 -0700399 */
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700400 private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state) {
401 return (state.installed && !state.hidden)
Amith Yamasani655d0e22013-06-12 14:19:10 -0700402 || (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700403 }
404
Christopher Tateba629da2013-11-13 17:42:28 -0800405 public static boolean isAvailable(PackageUserState state) {
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700406 return checkUseInstalledOrHidden(0, state);
Christopher Tateba629da2013-11-13 17:42:28 -0800407 }
408
Amith Yamasani13593602012-03-22 16:16:17 -0700409 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Amith Yamasani483f3b02012-03-13 16:08:00 -0700410 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svetoslavc6d1c342015-02-26 14:44:43 -0800411 Set<String> grantedPermissions, PackageUserState state, int userId) {
Amith Yamasani742a6712011-05-04 14:49:28 -0700412
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700413 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700414 return null;
415 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416 PackageInfo pi = new PackageInfo();
417 pi.packageName = p.packageName;
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700418 pi.splitNames = p.splitNames;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 pi.versionCode = p.mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800420 pi.baseRevisionCode = p.baseRevisionCode;
421 pi.splitRevisionCodes = p.splitRevisionCodes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 pi.versionName = p.mVersionName;
423 pi.sharedUserId = p.mSharedUserId;
424 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700425 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800426 pi.installLocation = p.installLocation;
Jeff Hao272bf3a2014-10-08 13:34:43 -0700427 pi.coreApp = p.coreApp;
Amith Yamasani0d8750d2013-05-01 15:25:28 -0700428 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
429 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
430 pi.requiredForAllUsers = p.mRequiredForAllUsers;
431 }
Amith Yamasani0ac1fc92013-03-27 18:56:08 -0700432 pi.restrictedAccountType = p.mRestrictedAccountType;
Amith Yamasaniccbe3892013-04-12 17:52:42 -0700433 pi.requiredAccountType = p.mRequiredAccountType;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100434 pi.overlayTarget = p.mOverlayTarget;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700435 pi.firstInstallTime = firstInstallTime;
436 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 if ((flags&PackageManager.GET_GIDS) != 0) {
438 pi.gids = gids;
439 }
440 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700441 int N = p.configPreferences != null ? p.configPreferences.size() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 if (N > 0) {
443 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700444 p.configPreferences.toArray(pi.configPreferences);
445 }
446 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
447 if (N > 0) {
448 pi.reqFeatures = new FeatureInfo[N];
449 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800450 }
Adam Lesinskid3edfde2014-08-08 17:32:44 -0700451 N = p.featureGroups != null ? p.featureGroups.size() : 0;
452 if (N > 0) {
453 pi.featureGroups = new FeatureGroupInfo[N];
454 p.featureGroups.toArray(pi.featureGroups);
455 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 }
457 if ((flags&PackageManager.GET_ACTIVITIES) != 0) {
458 int N = p.activities.size();
459 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700460 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
461 pi.activities = new ActivityInfo[N];
462 } else {
463 int num = 0;
464 for (int i=0; i<N; i++) {
465 if (p.activities.get(i).info.enabled) num++;
466 }
467 pi.activities = new ActivityInfo[num];
468 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700469 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470 final Activity activity = p.activities.get(i);
471 if (activity.info.enabled
472 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Amith Yamasani742a6712011-05-04 14:49:28 -0700473 pi.activities[j++] = generateActivityInfo(p.activities.get(i), flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700474 state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 }
476 }
477 }
478 }
479 if ((flags&PackageManager.GET_RECEIVERS) != 0) {
480 int N = p.receivers.size();
481 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700482 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
483 pi.receivers = new ActivityInfo[N];
484 } else {
485 int num = 0;
486 for (int i=0; i<N; i++) {
487 if (p.receivers.get(i).info.enabled) num++;
488 }
489 pi.receivers = new ActivityInfo[num];
490 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700491 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800492 final Activity activity = p.receivers.get(i);
493 if (activity.info.enabled
494 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Amith Yamasani13593602012-03-22 16:16:17 -0700495 pi.receivers[j++] = generateActivityInfo(p.receivers.get(i), flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700496 state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 }
498 }
499 }
500 }
501 if ((flags&PackageManager.GET_SERVICES) != 0) {
502 int N = p.services.size();
503 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700504 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
505 pi.services = new ServiceInfo[N];
506 } else {
507 int num = 0;
508 for (int i=0; i<N; i++) {
509 if (p.services.get(i).info.enabled) num++;
510 }
511 pi.services = new ServiceInfo[num];
512 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700513 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800514 final Service service = p.services.get(i);
515 if (service.info.enabled
516 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700517 pi.services[j++] = generateServiceInfo(p.services.get(i), flags,
518 state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519 }
520 }
521 }
522 }
523 if ((flags&PackageManager.GET_PROVIDERS) != 0) {
524 int N = p.providers.size();
525 if (N > 0) {
Dianne Hackborn7eca6872009-09-28 23:57:05 -0700526 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
527 pi.providers = new ProviderInfo[N];
528 } else {
529 int num = 0;
530 for (int i=0; i<N; i++) {
531 if (p.providers.get(i).info.enabled) num++;
532 }
533 pi.providers = new ProviderInfo[num];
534 }
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700535 for (int i=0, j=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 final Provider provider = p.providers.get(i);
537 if (provider.info.enabled
538 || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700539 pi.providers[j++] = generateProviderInfo(p.providers.get(i), flags,
540 state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800541 }
542 }
543 }
544 }
545 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
546 int N = p.instrumentation.size();
547 if (N > 0) {
548 pi.instrumentation = new InstrumentationInfo[N];
549 for (int i=0; i<N; i++) {
550 pi.instrumentation[i] = generateInstrumentationInfo(
551 p.instrumentation.get(i), flags);
552 }
553 }
554 }
555 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
556 int N = p.permissions.size();
557 if (N > 0) {
558 pi.permissions = new PermissionInfo[N];
559 for (int i=0; i<N; i++) {
560 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
561 }
562 }
563 N = p.requestedPermissions.size();
564 if (N > 0) {
565 pi.requestedPermissions = new String[N];
Dianne Hackborne639da72012-02-21 15:11:13 -0800566 pi.requestedPermissionsFlags = new int[N];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800567 for (int i=0; i<N; i++) {
Dianne Hackborne639da72012-02-21 15:11:13 -0800568 final String perm = p.requestedPermissions.get(i);
569 pi.requestedPermissions[i] = perm;
Svet Ganov3695b8a2015-03-24 16:30:25 -0700570 // The notion of required permissions is deprecated but for compatibility.
Svetoslavc6d1c342015-02-26 14:44:43 -0800571 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800572 if (grantedPermissions != null && grantedPermissions.contains(perm)) {
573 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800575 }
576 }
577 }
578 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700579 int N = (p.mSignatures != null) ? p.mSignatures.length : 0;
580 if (N > 0) {
581 pi.signatures = new Signature[N];
582 System.arraycopy(p.mSignatures, 0, pi.signatures, 0, N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 }
584 }
585 return pi;
586 }
587
Jeff Sharkey275e0852014-06-17 18:18:49 -0700588 private static Certificate[][] loadCertificates(StrictJarFile jarFile, ZipEntry entry)
589 throws PackageParserException {
590 InputStream is = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591 try {
592 // We must read the stream for the JarEntry to retrieve
593 // its certificates.
Jeff Sharkey275e0852014-06-17 18:18:49 -0700594 is = jarFile.getInputStream(entry);
595 readFullyIgnoringContents(is);
596 return jarFile.getCertificateChains(entry);
597 } catch (IOException | RuntimeException e) {
598 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
599 "Failed reading " + entry.getName() + " in " + jarFile, e);
600 } finally {
601 IoUtils.closeQuietly(is);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800603 }
604
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800605 public final static int PARSE_IS_SYSTEM = 1<<0;
606 public final static int PARSE_CHATTY = 1<<1;
607 public final static int PARSE_MUST_BE_APK = 1<<2;
608 public final static int PARSE_IGNORE_PROCESSES = 1<<3;
609 public final static int PARSE_FORWARD_LOCK = 1<<4;
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -0700610 public final static int PARSE_EXTERNAL_STORAGE = 1<<5;
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700611 public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
Christopher Tateccbf84f2013-05-08 15:25:41 -0700612 public final static int PARSE_IS_PRIVILEGED = 1<<7;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700613 public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700614 public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
615
616 private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800617
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700618 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700619 * Used to sort a set of APKs based on their split names, always placing the
620 * base APK (with {@code null} split name) first.
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700621 */
Jeff Sharkey275e0852014-06-17 18:18:49 -0700622 private static class SplitNameComparator implements Comparator<String> {
623 @Override
624 public int compare(String lhs, String rhs) {
625 if (lhs == null) {
626 return -1;
627 } else if (rhs == null) {
628 return 1;
629 } else {
630 return lhs.compareTo(rhs);
631 }
632 }
633 }
634
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700635 /**
636 * Parse only lightweight details about the package at the given location.
637 * Automatically detects if the package is a monolithic style (single APK
638 * file) or cluster style (directory of APKs).
639 * <p>
640 * This performs sanity checking on cluster style packages, such as
641 * requiring identical package name and version codes, a single base APK,
642 * and unique split names.
643 *
644 * @see PackageParser#parsePackage(File, int)
645 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700646 public static PackageLite parsePackageLite(File packageFile, int flags)
647 throws PackageParserException {
648 if (packageFile.isDirectory()) {
649 return parseClusterPackageLite(packageFile, flags);
650 } else {
651 return parseMonolithicPackageLite(packageFile, flags);
652 }
653 }
654
655 private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
656 throws PackageParserException {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700657 final ApkLite baseApk = parseApkLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700658 final String packagePath = packageFile.getAbsolutePath();
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800659 return new PackageLite(packagePath, baseApk, null, null, null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700660 }
661
662 private static PackageLite parseClusterPackageLite(File packageDir, int flags)
663 throws PackageParserException {
664 final File[] files = packageDir.listFiles();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700665 if (ArrayUtils.isEmpty(files)) {
666 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
667 "No packages found in split");
668 }
669
Jeff Sharkey275e0852014-06-17 18:18:49 -0700670 String packageName = null;
671 int versionCode = 0;
672
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700673 final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700674 for (File file : files) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700675 if (isApkFile(file)) {
676 final ApkLite lite = parseApkLite(file, flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -0700677
678 // Assert that all package names and version codes are
679 // consistent with the first one we encounter.
680 if (packageName == null) {
681 packageName = lite.packageName;
682 versionCode = lite.versionCode;
683 } else {
684 if (!packageName.equals(lite.packageName)) {
685 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
686 "Inconsistent package " + lite.packageName + " in " + file
687 + "; expected " + packageName);
688 }
689 if (versionCode != lite.versionCode) {
690 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
691 "Inconsistent version " + lite.versionCode + " in " + file
692 + "; expected " + versionCode);
693 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700694 }
695
Jeff Sharkey275e0852014-06-17 18:18:49 -0700696 // Assert that each split is defined only once
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700697 if (apks.put(lite.splitName, lite) != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700698 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
699 "Split name " + lite.splitName
700 + " defined more than once; most recent was " + file);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700701 }
702 }
703 }
704
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700705 final ApkLite baseApk = apks.remove(null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700706 if (baseApk == null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700707 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
Jeff Sharkey73767b92014-07-04 20:18:13 -0700708 "Missing base APK in " + packageDir);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700709 }
710
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700711 // Always apply deterministic ordering based on splitName
712 final int size = apks.size();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700713
Jeff Sharkey73767b92014-07-04 20:18:13 -0700714 String[] splitNames = null;
715 String[] splitCodePaths = null;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800716 int[] splitRevisionCodes = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700717 if (size > 0) {
718 splitNames = new String[size];
719 splitCodePaths = new String[size];
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800720 splitRevisionCodes = new int[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700721
722 splitNames = apks.keySet().toArray(splitNames);
723 Arrays.sort(splitNames, sSplitNameComparator);
724
725 for (int i = 0; i < size; i++) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700726 splitCodePaths[i] = apks.get(splitNames[i]).codePath;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800727 splitRevisionCodes[i] = apks.get(splitNames[i]).revisionCode;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700728 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700729 }
730
Jeff Sharkey73767b92014-07-04 20:18:13 -0700731 final String codePath = packageDir.getAbsolutePath();
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800732 return new PackageLite(codePath, baseApk, splitNames, splitCodePaths,
733 splitRevisionCodes);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700734 }
735
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700736 /**
737 * Parse the package at the given location. Automatically detects if the
738 * package is a monolithic style (single APK file) or cluster style
739 * (directory of APKs).
740 * <p>
741 * This performs sanity checking on cluster style packages, such as
742 * requiring identical package name and version codes, a single base APK,
743 * and unique split names.
744 * <p>
745 * Note that this <em>does not</em> perform signature verification; that
746 * must be done separately in {@link #collectCertificates(Package, int)}.
747 *
748 * @see #parsePackageLite(File, int)
749 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700750 public Package parsePackage(File packageFile, int flags) throws PackageParserException {
751 if (packageFile.isDirectory()) {
752 return parseClusterPackage(packageFile, flags);
753 } else {
754 return parseMonolithicPackage(packageFile, flags);
755 }
756 }
757
758 /**
759 * Parse all APKs contained in the given directory, treating them as a
760 * single package. This also performs sanity checking, such as requiring
761 * identical package name and version codes, a single base APK, and unique
762 * split names.
763 * <p>
764 * Note that this <em>does not</em> perform signature verification; that
765 * must be done separately in {@link #collectCertificates(Package, int)}.
766 */
767 private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
768 final PackageLite lite = parseClusterPackageLite(packageDir, 0);
769
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700770 if (mOnlyCoreApps && !lite.coreApp) {
771 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
772 "Not a coreApp: " + packageDir);
773 }
774
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700775 final AssetManager assets = new AssetManager();
776 try {
777 // Load the base and all splits into the AssetManager
778 // so that resources can be overriden when parsing the manifests.
779 loadApkIntoAssetManager(assets, lite.baseCodePath, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700780
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700781 if (!ArrayUtils.isEmpty(lite.splitCodePaths)) {
782 for (String path : lite.splitCodePaths) {
783 loadApkIntoAssetManager(assets, path, flags);
784 }
Jeff Sharkey73767b92014-07-04 20:18:13 -0700785 }
Jeff Sharkey73767b92014-07-04 20:18:13 -0700786
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700787 final File baseApk = new File(lite.baseCodePath);
788 final Package pkg = parseBaseApk(baseApk, assets, flags);
789 if (pkg == null) {
790 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
791 "Failed to parse base APK: " + baseApk);
792 }
793
794 if (!ArrayUtils.isEmpty(lite.splitNames)) {
795 final int num = lite.splitNames.length;
796 pkg.splitNames = lite.splitNames;
797 pkg.splitCodePaths = lite.splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800798 pkg.splitRevisionCodes = lite.splitRevisionCodes;
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700799 pkg.splitFlags = new int[num];
Alex Klyubinb9f8a522015-02-03 11:12:59 -0800800 pkg.splitPrivateFlags = new int[num];
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700801
802 for (int i = 0; i < num; i++) {
803 parseSplitApk(pkg, i, assets, flags);
804 }
805 }
806
807 pkg.codePath = packageDir.getAbsolutePath();
808 return pkg;
809 } finally {
810 IoUtils.closeQuietly(assets);
811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 }
813
Jeff Sharkey275e0852014-06-17 18:18:49 -0700814 /**
815 * Parse the given APK file, treating it as as a single monolithic package.
816 * <p>
817 * Note that this <em>does not</em> perform signature verification; that
818 * must be done separately in {@link #collectCertificates(Package, int)}.
Jeff Sharkeyd7460572014-07-06 20:44:55 -0700819 *
820 * @deprecated external callers should move to
821 * {@link #parsePackage(File, int)}. Eventually this method will
822 * be marked private.
Jeff Sharkey275e0852014-06-17 18:18:49 -0700823 */
Jeff Sharkeyd7460572014-07-06 20:44:55 -0700824 @Deprecated
Jeff Sharkey275e0852014-06-17 18:18:49 -0700825 public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700826 if (mOnlyCoreApps) {
827 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
828 if (!lite.coreApp) {
829 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
830 "Not a coreApp: " + apkFile);
831 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700832 }
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700833
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700834 final AssetManager assets = new AssetManager();
835 try {
836 final Package pkg = parseBaseApk(apkFile, assets, flags);
837 pkg.codePath = apkFile.getAbsolutePath();
838 return pkg;
839 } finally {
840 IoUtils.closeQuietly(assets);
841 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700842 }
843
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700844 private static int loadApkIntoAssetManager(AssetManager assets, String apkPath, int flags)
845 throws PackageParserException {
846 if ((flags & PARSE_MUST_BE_APK) != 0 && !isApkPath(apkPath)) {
847 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
848 "Invalid package file: " + apkPath);
849 }
850
851 // The AssetManager guarantees uniqueness for asset paths, so if this asset path
852 // already exists in the AssetManager, addAssetPath will only return the cookie
853 // assigned to it.
854 int cookie = assets.addAssetPath(apkPath);
855 if (cookie == 0) {
856 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
857 "Failed adding asset path: " + apkPath);
858 }
859 return cookie;
860 }
861
862 private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
863 throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700864 final String apkPath = apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -0700865
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700866 String volumeUuid = null;
867 if (apkPath.startsWith(MNT_EXPAND)) {
868 final int end = apkPath.indexOf('/', MNT_EXPAND.length());
869 volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
870 }
871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872 mParseError = PackageManager.INSTALL_SUCCEEDED;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700873 mArchiveSourcePath = apkFile.getAbsolutePath();
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700874
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700875 if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700877 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
878
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800879 Resources res = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700880 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700882 res = new Resources(assets, mMetrics, null);
883 assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
884 Build.VERSION.RESOURCES_SDK_INT);
885 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
886
887 final String[] outError = new String[1];
888 final Package pkg = parseBaseApk(res, parser, flags, outError);
889 if (pkg == null) {
890 throw new PackageParserException(mParseError,
891 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800892 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700893
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700894 pkg.volumeUuid = volumeUuid;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700895 pkg.baseCodePath = apkPath;
896 pkg.mSignatures = null;
897
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700898 return pkg;
899
900 } catch (PackageParserException e) {
901 throw e;
902 } catch (Exception e) {
903 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -0700904 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700905 } finally {
906 IoUtils.closeQuietly(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800907 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908 }
909
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700910 private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700911 throws PackageParserException {
912 final String apkPath = pkg.splitCodePaths[splitIndex];
913 final File apkFile = new File(apkPath);
Jeff Sharkey275e0852014-06-17 18:18:49 -0700914
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700915 mParseError = PackageManager.INSTALL_SUCCEEDED;
916 mArchiveSourcePath = apkPath;
917
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700918 if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
919
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700920 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
921
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700922 Resources res = null;
923 XmlResourceParser parser = null;
924 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700925 res = new Resources(assets, mMetrics, null);
926 assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
927 Build.VERSION.RESOURCES_SDK_INT);
928 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
929
930 final String[] outError = new String[1];
931 pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
932 if (pkg == null) {
933 throw new PackageParserException(mParseError,
934 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
935 }
936
937 } catch (PackageParserException e) {
938 throw e;
939 } catch (Exception e) {
940 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -0700941 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700942 } finally {
943 IoUtils.closeQuietly(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700944 }
945 }
946
947 /**
948 * Parse the manifest of a <em>split APK</em>.
949 * <p>
950 * Note that split APKs have many more restrictions on what they're capable
951 * of doing, so many valid features of a base APK have been carefully
952 * omitted here.
953 */
954 private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkey78a13012014-07-15 20:18:34 -0700955 int splitIndex, String[] outError) throws XmlPullParserException, IOException,
956 PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700957 AttributeSet attrs = parser;
958
Jeff Sharkey78a13012014-07-15 20:18:34 -0700959 // We parsed manifest tag earlier; just skip past it
960 parsePackageSplitNames(parser, attrs, flags);
961
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700962 mParseInstrumentationArgs = null;
963 mParseActivityArgs = null;
964 mParseServiceArgs = null;
965 mParseProviderArgs = null;
966
967 int type;
968
969 boolean foundApp = false;
970
971 int outerDepth = parser.getDepth();
972 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
973 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
974 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
975 continue;
976 }
977
978 String tagName = parser.getName();
979 if (tagName.equals("application")) {
980 if (foundApp) {
981 if (RIGID_PARSER) {
982 outError[0] = "<manifest> has more than one <application>";
983 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
984 return null;
985 } else {
986 Slog.w(TAG, "<manifest> has more than one <application>");
987 XmlUtils.skipCurrentTag(parser);
988 continue;
989 }
990 }
991
992 foundApp = true;
993 if (!parseSplitApplication(pkg, res, parser, attrs, flags, splitIndex, outError)) {
994 return null;
995 }
996
997 } else if (RIGID_PARSER) {
998 outError[0] = "Bad element under <manifest>: "
999 + parser.getName();
1000 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1001 return null;
1002
1003 } else {
1004 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1005 + " at " + mArchiveSourcePath + " "
1006 + parser.getPositionDescription());
1007 XmlUtils.skipCurrentTag(parser);
1008 continue;
1009 }
1010 }
1011
1012 if (!foundApp) {
1013 outError[0] = "<manifest> does not contain an <application>";
1014 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1015 }
1016
1017 return pkg;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001018 }
1019
Kenny Root6c918ce2013-04-02 14:04:24 -07001020 /**
1021 * Gathers the {@link ManifestDigest} for {@code pkg} if it exists in the
1022 * APK. If it successfully scanned the package and found the
1023 * {@code AndroidManifest.xml}, {@code true} is returned.
1024 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001025 public void collectManifestDigest(Package pkg) throws PackageParserException {
Jeff Sharkey032f2b22014-06-19 15:48:47 -07001026 pkg.manifestDigest = null;
1027
Jeff Sharkey275e0852014-06-17 18:18:49 -07001028 // TODO: extend to gather digest for split APKs
Kenny Root6c918ce2013-04-02 14:04:24 -07001029 try {
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07001030 final StrictJarFile jarFile = new StrictJarFile(pkg.baseCodePath);
Kenny Root6c918ce2013-04-02 14:04:24 -07001031 try {
Narayan Kamatheb565dc2013-12-12 16:54:33 +00001032 final ZipEntry je = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
Kenny Root6c918ce2013-04-02 14:04:24 -07001033 if (je != null) {
1034 pkg.manifestDigest = ManifestDigest.fromInputStream(jarFile.getInputStream(je));
1035 }
1036 } finally {
1037 jarFile.close();
1038 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001039 } catch (IOException | RuntimeException e) {
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001040 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1041 "Failed to collect manifest digest");
Kenny Root6c918ce2013-04-02 14:04:24 -07001042 }
1043 }
1044
Jeff Sharkey275e0852014-06-17 18:18:49 -07001045 /**
1046 * Collect certificates from all the APKs described in the given package,
1047 * populating {@link Package#mSignatures}. This also asserts that all APK
1048 * contents are signed correctly and consistently.
1049 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001050 public void collectCertificates(Package pkg, int flags) throws PackageParserException {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001051 pkg.mCertificates = null;
1052 pkg.mSignatures = null;
1053 pkg.mSigningKeys = null;
1054
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07001055 collectCertificates(pkg, new File(pkg.baseCodePath), flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001056
1057 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
1058 for (String splitCodePath : pkg.splitCodePaths) {
1059 collectCertificates(pkg, new File(splitCodePath), flags);
1060 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001061 }
1062 }
1063
Jeff Sharkey275e0852014-06-17 18:18:49 -07001064 private static void collectCertificates(Package pkg, File apkFile, int flags)
1065 throws PackageParserException {
1066 final String apkPath = apkFile.getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067
Jeff Sharkey275e0852014-06-17 18:18:49 -07001068 StrictJarFile jarFile = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001069 try {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001070 jarFile = new StrictJarFile(apkPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071
Jeff Sharkey275e0852014-06-17 18:18:49 -07001072 // Always verify manifest, regardless of source
1073 final ZipEntry manifestEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
1074 if (manifestEntry == null) {
1075 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1076 "Package " + apkPath + " has no manifest");
1077 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001078
Jeff Sharkey275e0852014-06-17 18:18:49 -07001079 final List<ZipEntry> toVerify = new ArrayList<>();
1080 toVerify.add(manifestEntry);
1081
1082 // If we're parsing an untrusted package, verify all contents
1083 if ((flags & PARSE_IS_SYSTEM) == 0) {
1084 final Iterator<ZipEntry> i = jarFile.iterator();
1085 while (i.hasNext()) {
1086 final ZipEntry entry = i.next();
1087
1088 if (entry.isDirectory()) continue;
1089 if (entry.getName().startsWith("META-INF/")) continue;
1090 if (entry.getName().equals(ANDROID_MANIFEST_FILENAME)) continue;
1091
1092 toVerify.add(entry);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001094 }
1095
1096 // Verify that entries are signed consistently with the first entry
1097 // we encountered. Note that for splits, certificates may have
1098 // already been populated during an earlier parse of a base APK.
1099 for (ZipEntry entry : toVerify) {
1100 final Certificate[][] entryCerts = loadCertificates(jarFile, entry);
1101 if (ArrayUtils.isEmpty(entryCerts)) {
1102 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1103 "Package " + apkPath + " has no certificates at entry "
1104 + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 }
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001106 final Signature[] entrySignatures = convertToSignatures(entryCerts);
Kenny Rootd2d29252011-08-08 11:27:57 -07001107
Jeff Sharkey275e0852014-06-17 18:18:49 -07001108 if (pkg.mCertificates == null) {
1109 pkg.mCertificates = entryCerts;
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001110 pkg.mSignatures = entrySignatures;
dcashman55b10782014-04-09 14:20:38 -07001111 pkg.mSigningKeys = new ArraySet<PublicKey>();
1112 for (int i=0; i < entryCerts.length; i++) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001113 pkg.mSigningKeys.add(entryCerts[i][0].getPublicKey());
Kenny Rootbcc954d2011-08-08 16:19:08 -07001114 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001115 } else {
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001116 if (!Signature.areExactMatch(pkg.mSignatures, entrySignatures)) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001117 throw new PackageParserException(
1118 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, "Package " + apkPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 + " has mismatched certificates at entry "
Jeff Sharkey275e0852014-06-17 18:18:49 -07001120 + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 }
1122 }
1123 }
Jeff Sharkeybc097552014-09-09 14:57:26 -07001124 } catch (GeneralSecurityException e) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001125 throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING,
1126 "Failed to collect certificates from " + apkPath, e);
Jeff Sharkeybc097552014-09-09 14:57:26 -07001127 } catch (IOException | RuntimeException e) {
1128 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1129 "Failed to collect certificates from " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001130 } finally {
1131 closeQuietly(jarFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001132 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001133 }
1134
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001135 private static Signature[] convertToSignatures(Certificate[][] certs)
1136 throws CertificateEncodingException {
1137 final Signature[] res = new Signature[certs.length];
1138 for (int i = 0; i < certs.length; i++) {
1139 res[i] = new Signature(certs[i]);
1140 }
1141 return res;
1142 }
1143
Jeff Sharkey275e0852014-06-17 18:18:49 -07001144 /**
1145 * Utility method that retrieves lightweight details about a single APK
1146 * file, including package name, split name, and install location.
1147 *
1148 * @param apkFile path to a single APK
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001149 * @param flags optional parse flags, such as
1150 * {@link #PARSE_COLLECT_CERTIFICATES}
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001151 */
Jeff Sharkey275e0852014-06-17 18:18:49 -07001152 public static ApkLite parseApkLite(File apkFile, int flags)
1153 throws PackageParserException {
1154 final String apkPath = apkFile.getAbsolutePath();
1155
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001156 AssetManager assets = null;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001157 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001158 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001159 assets = new AssetManager();
1160 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 -08001161 Build.VERSION.RESOURCES_SDK_INT);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001162
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001163 int cookie = assets.addAssetPath(apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001164 if (cookie == 0) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001165 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1166 "Failed to parse " + apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001167 }
1168
Kenny Root05ca4c92011-09-15 10:36:25 -07001169 final DisplayMetrics metrics = new DisplayMetrics();
1170 metrics.setToDefaults();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001171
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001172 final Resources res = new Resources(assets, metrics, null);
1173 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Kenny Root05ca4c92011-09-15 10:36:25 -07001174
Jeff Sharkey275e0852014-06-17 18:18:49 -07001175 final Signature[] signatures;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001176 if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
1177 // TODO: factor signature related items out of Package object
1178 final Package tempPkg = new Package(null);
1179 collectCertificates(tempPkg, apkFile, 0);
1180 signatures = tempPkg.mSignatures;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001181 } else {
1182 signatures = null;
1183 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001184
Jeff Sharkey275e0852014-06-17 18:18:49 -07001185 final AttributeSet attrs = parser;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -07001186 return parseApkLite(apkPath, res, parser, attrs, flags, signatures);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001187
1188 } catch (XmlPullParserException | IOException | RuntimeException e) {
1189 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1190 "Failed to parse " + apkPath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001191 } finally {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001192 IoUtils.closeQuietly(parser);
1193 IoUtils.closeQuietly(assets);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001195 }
1196
1197 private static String validateName(String name, boolean requiresSeparator) {
1198 final int N = name.length();
1199 boolean hasSep = false;
1200 boolean front = true;
1201 for (int i=0; i<N; i++) {
1202 final char c = name.charAt(i);
1203 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1204 front = false;
1205 continue;
1206 }
1207 if (!front) {
1208 if ((c >= '0' && c <= '9') || c == '_') {
1209 continue;
1210 }
1211 }
1212 if (c == '.') {
1213 hasSep = true;
1214 front = true;
1215 continue;
1216 }
1217 return "bad character '" + c + "'";
1218 }
1219 return hasSep || !requiresSeparator
1220 ? null : "must have at least one '.' separator";
1221 }
1222
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001223 private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
1224 AttributeSet attrs, int flags) throws IOException, XmlPullParserException,
1225 PackageParserException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001226
1227 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001228 while ((type = parser.next()) != XmlPullParser.START_TAG
1229 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001230 }
1231
Kenny Rootd2d29252011-08-08 11:27:57 -07001232 if (type != XmlPullParser.START_TAG) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001233 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1234 "No start tag found");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236 if (!parser.getName().equals("manifest")) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001237 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1238 "No <manifest> tag");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001239 }
1240
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001241 final String packageName = attrs.getAttributeValue(null, "package");
1242 if (!"android".equals(packageName)) {
1243 final String error = validateName(packageName, true);
1244 if (error != null) {
1245 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1246 "Invalid manifest package: " + error);
1247 }
1248 }
1249
Jeff Sharkey275e0852014-06-17 18:18:49 -07001250 String splitName = attrs.getAttributeValue(null, "split");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001251 if (splitName != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001252 if (splitName.length() == 0) {
1253 splitName = null;
1254 } else {
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001255 final String error = validateName(splitName, false);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001256 if (error != null) {
1257 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1258 "Invalid manifest split: " + error);
1259 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001260 }
1261 }
1262
1263 return Pair.create(packageName.intern(),
1264 (splitName != null) ? splitName.intern() : splitName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001265 }
1266
Jeff Sharkeybe520fb2014-07-04 18:23:17 -07001267 private static ApkLite parseApkLite(String codePath, Resources res, XmlPullParser parser,
Jeff Sharkey275e0852014-06-17 18:18:49 -07001268 AttributeSet attrs, int flags, Signature[] signatures) throws IOException,
1269 XmlPullParserException, PackageParserException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001270 final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs, flags);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001271
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001272 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001273 int versionCode = 0;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001274 int revisionCode = 0;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001275 boolean coreApp = false;
Narayan Kamathff110bd2014-07-04 18:30:45 +01001276 boolean multiArch = false;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001277 boolean extractNativeLibs = true;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001278
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001279 for (int i = 0; i < attrs.getAttributeCount(); i++) {
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001280 final String attr = attrs.getAttributeName(i);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001281 if (attr.equals("installLocation")) {
1282 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001283 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001284 } else if (attr.equals("versionCode")) {
1285 versionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001286 } else if (attr.equals("revisionCode")) {
1287 revisionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001288 } else if (attr.equals("coreApp")) {
1289 coreApp = attrs.getAttributeBooleanValue(i, false);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001290 }
1291 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001292
1293 // Only search the tree when the tag is directly below <manifest>
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001294 int type;
Kenny Root05ca4c92011-09-15 10:36:25 -07001295 final int searchDepth = parser.getDepth() + 1;
1296
1297 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
1298 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1299 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
1300 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1301 continue;
1302 }
1303
1304 if (parser.getDepth() == searchDepth && "package-verifier".equals(parser.getName())) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001305 final VerifierInfo verifier = parseVerifier(res, parser, attrs, flags);
Kenny Root05ca4c92011-09-15 10:36:25 -07001306 if (verifier != null) {
1307 verifiers.add(verifier);
1308 }
1309 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001310
1311 if (parser.getDepth() == searchDepth && "application".equals(parser.getName())) {
1312 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1313 final String attr = attrs.getAttributeName(i);
1314 if ("multiArch".equals(attr)) {
1315 multiArch = attrs.getAttributeBooleanValue(i, false);
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001316 }
1317 if ("extractNativeLibs".equals(attr)) {
1318 extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
Narayan Kamatha8755a82014-07-15 12:26:35 +01001319 }
1320 }
1321 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001322 }
1323
Jeff Sharkeybe520fb2014-07-04 18:23:17 -07001324 return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode,
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001325 revisionCode, installLocation, verifiers, signatures, coreApp, multiArch,
1326 extractNativeLibs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001327 }
1328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 /**
1330 * Temporary.
1331 */
1332 static public Signature stringToSignature(String str) {
1333 final int N = str.length();
1334 byte[] sig = new byte[N];
1335 for (int i=0; i<N; i++) {
1336 sig[i] = (byte)str.charAt(i);
1337 }
1338 return new Signature(sig);
1339 }
1340
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001341 /**
1342 * Parse the manifest of a <em>base APK</em>.
1343 * <p>
1344 * When adding new features, carefully consider if they should also be
1345 * supported by split APKs.
1346 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001347 private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001348 String[] outError) throws XmlPullParserException, IOException {
1349 final boolean trustedOverlay = (flags & PARSE_TRUSTED_OVERLAY) != 0;
1350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 AttributeSet attrs = parser;
1352
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001353 mParseInstrumentationArgs = null;
1354 mParseActivityArgs = null;
1355 mParseServiceArgs = null;
1356 mParseProviderArgs = null;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001357
1358 final String pkgName;
1359 final String splitName;
1360 try {
1361 Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs, flags);
1362 pkgName = packageSplit.first;
1363 splitName = packageSplit.second;
1364 } catch (PackageParserException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001365 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1366 return null;
1367 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 int type;
1370
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001371 if (!TextUtils.isEmpty(splitName)) {
1372 outError[0] = "Expected base APK, but found split " + splitName;
1373 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1374 return null;
1375 }
1376
1377 final Package pkg = new Package(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378 boolean foundApp = false;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 TypedArray sa = res.obtainAttributes(attrs,
1381 com.android.internal.R.styleable.AndroidManifest);
Dianne Hackborn8472e612014-01-23 17:57:20 -08001382 pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001384 pkg.baseRevisionCode = sa.getInteger(
1385 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001386 pkg.mVersionName = sa.getNonConfigurationString(
1387 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001388 if (pkg.mVersionName != null) {
1389 pkg.mVersionName = pkg.mVersionName.intern();
1390 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001391 String str = sa.getNonConfigurationString(
1392 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
1393 if (str != null && str.length() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001394 String nameError = validateName(str, true);
1395 if (nameError != null && !"android".equals(pkgName)) {
1396 outError[0] = "<manifest> specifies bad sharedUserId name \""
1397 + str + "\": " + nameError;
1398 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
1399 return null;
1400 }
1401 pkg.mSharedUserId = str.intern();
1402 pkg.mSharedUserLabel = sa.getResourceId(
1403 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
1404 }
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -08001405
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08001406 pkg.installLocation = sa.getInteger(
1407 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001408 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -07001409 pkg.applicationInfo.installLocation = pkg.installLocation;
Kenny Root7cb9be22012-05-30 15:30:37 -07001410
Jeff Hao272bf3a2014-10-08 13:34:43 -07001411 pkg.coreApp = attrs.getAttributeBooleanValue(null, "coreApp", false);
1412
Alan Viverettefd274a02014-03-27 15:39:15 -07001413 sa.recycle();
1414
Kenny Root7cb9be22012-05-30 15:30:37 -07001415 /* Set the global "forward lock" flag */
1416 if ((flags & PARSE_FORWARD_LOCK) != 0) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08001417 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
Kenny Root7cb9be22012-05-30 15:30:37 -07001418 }
1419
1420 /* Set the global "on SD card" flag */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001421 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
Kenny Root7cb9be22012-05-30 15:30:37 -07001422 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
1423 }
1424
Dianne Hackborn723738c2009-06-25 19:48:04 -07001425 // Resource boolean are -1, so 1 means we don't know the value.
1426 int supportsSmallScreens = 1;
1427 int supportsNormalScreens = 1;
1428 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001429 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001430 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001431 int anyDensity = 1;
Dianne Hackborn723738c2009-06-25 19:48:04 -07001432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001433 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -07001434 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1435 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1436 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437 continue;
1438 }
1439
1440 String tagName = parser.getName();
1441 if (tagName.equals("application")) {
1442 if (foundApp) {
1443 if (RIGID_PARSER) {
1444 outError[0] = "<manifest> has more than one <application>";
1445 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1446 return null;
1447 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07001448 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 XmlUtils.skipCurrentTag(parser);
1450 continue;
1451 }
1452 }
1453
1454 foundApp = true;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001455 if (!parseBaseApplication(pkg, res, parser, attrs, flags, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 return null;
1457 }
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01001458 } else if (tagName.equals("overlay")) {
1459 pkg.mTrustedOverlay = trustedOverlay;
1460
1461 sa = res.obtainAttributes(attrs,
1462 com.android.internal.R.styleable.AndroidManifestResourceOverlay);
1463 pkg.mOverlayTarget = sa.getString(
1464 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
1465 pkg.mOverlayPriority = sa.getInt(
1466 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
1467 -1);
1468 sa.recycle();
1469
1470 if (pkg.mOverlayTarget == null) {
1471 outError[0] = "<overlay> does not specify a target package";
1472 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1473 return null;
1474 }
1475 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
1476 outError[0] = "<overlay> priority must be between 0 and 9999";
1477 mParseError =
1478 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1479 return null;
1480 }
1481 XmlUtils.skipCurrentTag(parser);
1482
dcashman989eb3712014-06-17 12:56:12 -07001483 } else if (tagName.equals("key-sets")) {
1484 if (!parseKeySets(pkg, res, parser, attrs, outError)) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08001485 return null;
1486 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 } else if (tagName.equals("permission-group")) {
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07001488 if (parsePermissionGroup(pkg, flags, res, parser, attrs, outError) == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489 return null;
1490 }
1491 } else if (tagName.equals("permission")) {
1492 if (parsePermission(pkg, res, parser, attrs, outError) == null) {
1493 return null;
1494 }
1495 } else if (tagName.equals("permission-tree")) {
1496 if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
1497 return null;
1498 }
1499 } else if (tagName.equals("uses-permission")) {
Svetoslav96a77162015-04-03 13:58:33 -07001500 if (!parseUsesPermission(pkg, res, parser, attrs)) {
1501 return null;
1502 }
1503 } else if (tagName.equals("uses-permission-sdk-m")) {
1504 if (!parseUsesPermission(pkg, res, parser, attrs)) {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07001505 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 } else if (tagName.equals("uses-configuration")) {
1508 ConfigurationInfo cPref = new ConfigurationInfo();
1509 sa = res.obtainAttributes(attrs,
1510 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
1511 cPref.reqTouchScreen = sa.getInt(
1512 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
1513 Configuration.TOUCHSCREEN_UNDEFINED);
1514 cPref.reqKeyboardType = sa.getInt(
1515 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
1516 Configuration.KEYBOARD_UNDEFINED);
1517 if (sa.getBoolean(
1518 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
1519 false)) {
1520 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
1521 }
1522 cPref.reqNavigation = sa.getInt(
1523 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
1524 Configuration.NAVIGATION_UNDEFINED);
1525 if (sa.getBoolean(
1526 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
1527 false)) {
1528 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
1529 }
1530 sa.recycle();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001531 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532
1533 XmlUtils.skipCurrentTag(parser);
1534
Suchi Amalapurapud299b812009-06-05 10:26:19 -07001535 } else if (tagName.equals("uses-feature")) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07001536 FeatureInfo fi = parseUsesFeature(res, attrs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001537 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
1538
Dianne Hackborn49237342009-08-27 20:08:01 -07001539 if (fi.name == null) {
1540 ConfigurationInfo cPref = new ConfigurationInfo();
1541 cPref.reqGlEsVersion = fi.reqGlEsVersion;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001542 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
Dianne Hackborn49237342009-08-27 20:08:01 -07001543 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07001544
1545 XmlUtils.skipCurrentTag(parser);
1546
Adam Lesinski2c72b682014-06-24 09:56:01 -07001547 } else if (tagName.equals("feature-group")) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07001548 FeatureGroupInfo group = new FeatureGroupInfo();
1549 ArrayList<FeatureInfo> features = null;
1550 final int innerDepth = parser.getDepth();
1551 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1552 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
1553 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1554 continue;
1555 }
Adam Lesinski2c72b682014-06-24 09:56:01 -07001556
Adam Lesinskid3edfde2014-08-08 17:32:44 -07001557 final String innerTagName = parser.getName();
1558 if (innerTagName.equals("uses-feature")) {
1559 FeatureInfo featureInfo = parseUsesFeature(res, attrs);
1560 // FeatureGroups are stricter and mandate that
1561 // any <uses-feature> declared are mandatory.
1562 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
1563 features = ArrayUtils.add(features, featureInfo);
1564 } else {
1565 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
1566 " at " + mArchiveSourcePath + " " +
1567 parser.getPositionDescription());
1568 }
1569 XmlUtils.skipCurrentTag(parser);
1570 }
1571
1572 if (features != null) {
1573 group.features = new FeatureInfo[features.size()];
1574 group.features = features.toArray(group.features);
1575 }
1576 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
Adam Lesinski2c72b682014-06-24 09:56:01 -07001577
Dianne Hackborn851a5412009-05-08 12:06:44 -07001578 } else if (tagName.equals("uses-sdk")) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001579 if (SDK_VERSION > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 sa = res.obtainAttributes(attrs,
1581 com.android.internal.R.styleable.AndroidManifestUsesSdk);
1582
Dianne Hackborn851a5412009-05-08 12:06:44 -07001583 int minVers = 0;
1584 String minCode = null;
1585 int targetVers = 0;
1586 String targetCode = null;
1587
1588 TypedValue val = sa.peekValue(
1589 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
1590 if (val != null) {
1591 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
1592 targetCode = minCode = val.string.toString();
1593 } else {
1594 // If it's not a string, it's an integer.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001595 targetVers = minVers = val.data;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001596 }
1597 }
1598
1599 val = sa.peekValue(
1600 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
1601 if (val != null) {
1602 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
1603 targetCode = minCode = val.string.toString();
1604 } else {
1605 // If it's not a string, it's an integer.
1606 targetVers = val.data;
1607 }
1608 }
1609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 sa.recycle();
1611
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001612 if (minCode != null) {
Dianne Hackbornffcda102014-04-24 13:06:27 -07001613 boolean allowedCodename = false;
1614 for (String codename : SDK_CODENAMES) {
1615 if (minCode.equals(codename)) {
1616 allowedCodename = true;
1617 break;
1618 }
1619 }
1620 if (!allowedCodename) {
1621 if (SDK_CODENAMES.length > 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001622 outError[0] = "Requires development platform " + minCode
Dianne Hackbornffcda102014-04-24 13:06:27 -07001623 + " (current platform is any of "
1624 + Arrays.toString(SDK_CODENAMES) + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001625 } else {
1626 outError[0] = "Requires development platform " + minCode
1627 + " but this is a release platform.";
1628 }
1629 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1630 return null;
1631 }
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001632 } else if (minVers > SDK_VERSION) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001633 outError[0] = "Requires newer sdk version #" + minVers
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001634 + " (current version is #" + SDK_VERSION + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001635 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1636 return null;
1637 }
1638
Dianne Hackborn851a5412009-05-08 12:06:44 -07001639 if (targetCode != null) {
Dianne Hackbornffcda102014-04-24 13:06:27 -07001640 boolean allowedCodename = false;
1641 for (String codename : SDK_CODENAMES) {
1642 if (targetCode.equals(codename)) {
1643 allowedCodename = true;
1644 break;
1645 }
1646 }
1647 if (!allowedCodename) {
1648 if (SDK_CODENAMES.length > 0) {
Dianne Hackborn851a5412009-05-08 12:06:44 -07001649 outError[0] = "Requires development platform " + targetCode
Dianne Hackbornffcda102014-04-24 13:06:27 -07001650 + " (current platform is any of "
1651 + Arrays.toString(SDK_CODENAMES) + ")";
Dianne Hackborn851a5412009-05-08 12:06:44 -07001652 } else {
1653 outError[0] = "Requires development platform " + targetCode
1654 + " but this is a release platform.";
1655 }
1656 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1657 return null;
1658 }
1659 // If the code matches, it definitely targets this SDK.
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001660 pkg.applicationInfo.targetSdkVersion
1661 = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
1662 } else {
1663 pkg.applicationInfo.targetSdkVersion = targetVers;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001664 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001665 }
1666
1667 XmlUtils.skipCurrentTag(parser);
1668
Dianne Hackborn723738c2009-06-25 19:48:04 -07001669 } else if (tagName.equals("supports-screens")) {
1670 sa = res.obtainAttributes(attrs,
1671 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
1672
Dianne Hackborndf6e9802011-05-26 14:20:23 -07001673 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
1674 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
1675 0);
1676 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
1677 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
1678 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07001679 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
1680 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
1681 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07001682
Dianne Hackborn723738c2009-06-25 19:48:04 -07001683 // This is a trick to get a boolean and still able to detect
1684 // if a value was actually set.
1685 supportsSmallScreens = sa.getInteger(
1686 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
1687 supportsSmallScreens);
1688 supportsNormalScreens = sa.getInteger(
1689 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
1690 supportsNormalScreens);
1691 supportsLargeScreens = sa.getInteger(
1692 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
1693 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001694 supportsXLargeScreens = sa.getInteger(
1695 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
1696 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001697 resizeable = sa.getInteger(
1698 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001699 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001700 anyDensity = sa.getInteger(
1701 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
1702 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07001703
1704 sa.recycle();
1705
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07001706 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn854060af2009-07-09 18:14:31 -07001707
1708 } else if (tagName.equals("protected-broadcast")) {
1709 sa = res.obtainAttributes(attrs,
1710 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
1711
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001712 // Note: don't allow this value to be a reference to a resource
1713 // that may change.
Dianne Hackborn854060af2009-07-09 18:14:31 -07001714 String name = sa.getNonResourceString(
1715 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
1716
1717 sa.recycle();
1718
1719 if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
1720 if (pkg.protectedBroadcasts == null) {
1721 pkg.protectedBroadcasts = new ArrayList<String>();
1722 }
1723 if (!pkg.protectedBroadcasts.contains(name)) {
1724 pkg.protectedBroadcasts.add(name.intern());
1725 }
1726 }
1727
1728 XmlUtils.skipCurrentTag(parser);
1729
1730 } else if (tagName.equals("instrumentation")) {
1731 if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) {
1732 return null;
1733 }
1734
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001735 } else if (tagName.equals("original-package")) {
1736 sa = res.obtainAttributes(attrs,
1737 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
1738
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001739 String orig =sa.getNonConfigurationString(
1740 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001741 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08001742 if (pkg.mOriginalPackages == null) {
1743 pkg.mOriginalPackages = new ArrayList<String>();
1744 pkg.mRealPackage = pkg.packageName;
1745 }
1746 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001747 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001748
1749 sa.recycle();
1750
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001751 XmlUtils.skipCurrentTag(parser);
1752
1753 } else if (tagName.equals("adopt-permissions")) {
1754 sa = res.obtainAttributes(attrs,
1755 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
1756
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001757 String name = sa.getNonConfigurationString(
1758 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001759
1760 sa.recycle();
1761
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08001762 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001763 if (pkg.mAdoptPermissions == null) {
1764 pkg.mAdoptPermissions = new ArrayList<String>();
1765 }
1766 pkg.mAdoptPermissions.add(name);
1767 }
1768
1769 XmlUtils.skipCurrentTag(parser);
1770
Dianne Hackborna0b46c92010-10-21 15:32:06 -07001771 } else if (tagName.equals("uses-gl-texture")) {
1772 // Just skip this tag
1773 XmlUtils.skipCurrentTag(parser);
1774 continue;
1775
1776 } else if (tagName.equals("compatible-screens")) {
1777 // Just skip this tag
1778 XmlUtils.skipCurrentTag(parser);
1779 continue;
Michael Wrighteaeb1902013-09-05 18:15:57 -07001780 } else if (tagName.equals("supports-input")) {
1781 XmlUtils.skipCurrentTag(parser);
1782 continue;
Dianne Hackborna0b46c92010-10-21 15:32:06 -07001783
Dianne Hackborn854060af2009-07-09 18:14:31 -07001784 } else if (tagName.equals("eat-comment")) {
1785 // Just skip this tag
1786 XmlUtils.skipCurrentTag(parser);
1787 continue;
1788
1789 } else if (RIGID_PARSER) {
1790 outError[0] = "Bad element under <manifest>: "
1791 + parser.getName();
1792 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1793 return null;
1794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001795 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07001796 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07001797 + " at " + mArchiveSourcePath + " "
1798 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001799 XmlUtils.skipCurrentTag(parser);
1800 continue;
1801 }
1802 }
1803
1804 if (!foundApp && pkg.instrumentation.size() == 0) {
1805 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
1806 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1807 }
1808
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001809 final int NP = PackageParser.NEW_PERMISSIONS.length;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001810 StringBuilder implicitPerms = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001811 for (int ip=0; ip<NP; ip++) {
1812 final PackageParser.NewPermissionInfo npi
1813 = PackageParser.NEW_PERMISSIONS[ip];
1814 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
1815 break;
1816 }
1817 if (!pkg.requestedPermissions.contains(npi.name)) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001818 if (implicitPerms == null) {
1819 implicitPerms = new StringBuilder(128);
1820 implicitPerms.append(pkg.packageName);
1821 implicitPerms.append(": compat added ");
1822 } else {
1823 implicitPerms.append(' ');
1824 }
1825 implicitPerms.append(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001826 pkg.requestedPermissions.add(npi.name);
1827 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07001828 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001829 if (implicitPerms != null) {
Kenny Rootd2d29252011-08-08 11:27:57 -07001830 Slog.i(TAG, implicitPerms.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001831 }
Dianne Hackborn79245122012-03-12 10:51:26 -07001832
1833 final int NS = PackageParser.SPLIT_PERMISSIONS.length;
1834 for (int is=0; is<NS; is++) {
1835 final PackageParser.SplitPermissionInfo spi
1836 = PackageParser.SPLIT_PERMISSIONS[is];
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -07001837 if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
1838 || !pkg.requestedPermissions.contains(spi.rootPerm)) {
Dianne Hackborn5e4705a2012-04-06 12:55:53 -07001839 continue;
Dianne Hackborn79245122012-03-12 10:51:26 -07001840 }
1841 for (int in=0; in<spi.newPerms.length; in++) {
1842 final String perm = spi.newPerms[in];
1843 if (!pkg.requestedPermissions.contains(perm)) {
1844 pkg.requestedPermissions.add(perm);
Dianne Hackborn79245122012-03-12 10:51:26 -07001845 }
1846 }
1847 }
1848
Dianne Hackborn723738c2009-06-25 19:48:04 -07001849 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
1850 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001851 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001852 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
1853 }
1854 if (supportsNormalScreens != 0) {
1855 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
1856 }
1857 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
1858 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001859 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07001860 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
1861 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001862 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
1863 && pkg.applicationInfo.targetSdkVersion
1864 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
1865 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
1866 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001867 if (resizeable < 0 || (resizeable > 0
1868 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001869 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001870 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
1871 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001872 if (anyDensity < 0 || (anyDensity > 0
1873 && pkg.applicationInfo.targetSdkVersion
1874 >= android.os.Build.VERSION_CODES.DONUT)) {
1875 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07001876 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07001877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001878 return pkg;
1879 }
1880
Adam Lesinskid3edfde2014-08-08 17:32:44 -07001881 private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs)
1882 throws XmlPullParserException, IOException {
1883 FeatureInfo fi = new FeatureInfo();
1884 TypedArray sa = res.obtainAttributes(attrs,
1885 com.android.internal.R.styleable.AndroidManifestUsesFeature);
1886 // Note: don't allow this value to be a reference to a resource
1887 // that may change.
1888 fi.name = sa.getNonResourceString(
1889 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
1890 if (fi.name == null) {
1891 fi.reqGlEsVersion = sa.getInt(
1892 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
1893 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1894 }
1895 if (sa.getBoolean(
1896 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) {
1897 fi.flags |= FeatureInfo.FLAG_REQUIRED;
1898 }
1899 sa.recycle();
1900 return fi;
1901 }
1902
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07001903 private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser,
Svetoslav96a77162015-04-03 13:58:33 -07001904 AttributeSet attrs) throws XmlPullParserException, IOException {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07001905 TypedArray sa = res.obtainAttributes(attrs,
1906 com.android.internal.R.styleable.AndroidManifestUsesPermission);
1907
1908 // Note: don't allow this value to be a reference to a resource
1909 // that may change.
1910 String name = sa.getNonResourceString(
1911 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07001912
Christopher Tatefb0676a2013-09-16 16:34:52 -07001913 int maxSdkVersion = 0;
1914 TypedValue val = sa.peekValue(
1915 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
1916 if (val != null) {
1917 if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
1918 maxSdkVersion = val.data;
1919 }
1920 }
1921
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07001922 sa.recycle();
1923
Christopher Tatefb0676a2013-09-16 16:34:52 -07001924 if ((maxSdkVersion == 0) || (maxSdkVersion >= Build.VERSION.RESOURCES_SDK_INT)) {
1925 if (name != null) {
1926 int index = pkg.requestedPermissions.indexOf(name);
1927 if (index == -1) {
1928 pkg.requestedPermissions.add(name.intern());
Christopher Tatefb0676a2013-09-16 16:34:52 -07001929 } else {
Svetoslav96a77162015-04-03 13:58:33 -07001930 Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
1931 + name + " in package: " + pkg.packageName + " at: "
1932 + parser.getPositionDescription());
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07001933 }
1934 }
1935 }
1936
1937 XmlUtils.skipCurrentTag(parser);
1938 return true;
1939 }
1940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001941 private static String buildClassName(String pkg, CharSequence clsSeq,
1942 String[] outError) {
1943 if (clsSeq == null || clsSeq.length() <= 0) {
1944 outError[0] = "Empty class name in package " + pkg;
1945 return null;
1946 }
1947 String cls = clsSeq.toString();
1948 char c = cls.charAt(0);
1949 if (c == '.') {
1950 return (pkg + cls).intern();
1951 }
1952 if (cls.indexOf('.') < 0) {
1953 StringBuilder b = new StringBuilder(pkg);
1954 b.append('.');
1955 b.append(cls);
1956 return b.toString().intern();
1957 }
1958 if (c >= 'a' && c <= 'z') {
1959 return cls.intern();
1960 }
1961 outError[0] = "Bad class name " + cls + " in package " + pkg;
1962 return null;
1963 }
1964
1965 private static String buildCompoundName(String pkg,
1966 CharSequence procSeq, String type, String[] outError) {
1967 String proc = procSeq.toString();
1968 char c = proc.charAt(0);
1969 if (pkg != null && c == ':') {
1970 if (proc.length() < 2) {
1971 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
1972 + ": must be at least two characters";
1973 return null;
1974 }
1975 String subName = proc.substring(1);
1976 String nameError = validateName(subName, false);
1977 if (nameError != null) {
1978 outError[0] = "Invalid " + type + " name " + proc + " in package "
1979 + pkg + ": " + nameError;
1980 return null;
1981 }
1982 return (pkg + proc).intern();
1983 }
1984 String nameError = validateName(proc, true);
1985 if (nameError != null && !"system".equals(proc)) {
1986 outError[0] = "Invalid " + type + " name " + proc + " in package "
1987 + pkg + ": " + nameError;
1988 return null;
1989 }
1990 return proc.intern();
1991 }
1992
1993 private static String buildProcessName(String pkg, String defProc,
1994 CharSequence procSeq, int flags, String[] separateProcesses,
1995 String[] outError) {
1996 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
1997 return defProc != null ? defProc : pkg;
1998 }
1999 if (separateProcesses != null) {
2000 for (int i=separateProcesses.length-1; i>=0; i--) {
2001 String sp = separateProcesses[i];
2002 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
2003 return pkg;
2004 }
2005 }
2006 }
2007 if (procSeq == null || procSeq.length() <= 0) {
2008 return defProc;
2009 }
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002010 return buildCompoundName(pkg, procSeq, "process", outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002011 }
2012
2013 private static String buildTaskAffinityName(String pkg, String defProc,
2014 CharSequence procSeq, String[] outError) {
2015 if (procSeq == null) {
2016 return defProc;
2017 }
2018 if (procSeq.length() <= 0) {
2019 return null;
2020 }
2021 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
2022 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002023
dcashman989eb3712014-06-17 12:56:12 -07002024 private boolean parseKeySets(Package owner, Resources res,
Geremy Condraf1bcca82013-01-07 22:35:24 -08002025 XmlPullParser parser, AttributeSet attrs, String[] outError)
2026 throws XmlPullParserException, IOException {
dcashman989eb3712014-06-17 12:56:12 -07002027 // we've encountered the 'key-sets' tag
Geremy Condraf1bcca82013-01-07 22:35:24 -08002028 // all the keys and keysets that we want must be defined here
2029 // so we're going to iterate over the parser and pull out the things we want
2030 int outerDepth = parser.getDepth();
dcashman989eb3712014-06-17 12:56:12 -07002031 int currentKeySetDepth = -1;
Geremy Condraf1bcca82013-01-07 22:35:24 -08002032 int type;
dcashman989eb3712014-06-17 12:56:12 -07002033 String currentKeySet = null;
2034 ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
2035 ArraySet<String> upgradeKeySets = new ArraySet<String>();
2036 ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
2037 ArraySet<String> improperKeySets = new ArraySet<String>();
Geremy Condraf1bcca82013-01-07 22:35:24 -08002038 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2039 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2040 if (type == XmlPullParser.END_TAG) {
dcashman989eb3712014-06-17 12:56:12 -07002041 if (parser.getDepth() == currentKeySetDepth) {
2042 currentKeySet = null;
2043 currentKeySetDepth = -1;
Kenny Root37dca152013-07-10 14:01:49 -07002044 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002045 continue;
2046 }
dcashman989eb3712014-06-17 12:56:12 -07002047 String tagName = parser.getName();
2048 if (tagName.equals("key-set")) {
2049 if (currentKeySet != null) {
2050 Slog.w(TAG, "Improperly nested 'key-set' tag at "
2051 + parser.getPositionDescription());
2052 return false;
2053 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002054 final TypedArray sa = res.obtainAttributes(attrs,
dcashman989eb3712014-06-17 12:56:12 -07002055 com.android.internal.R.styleable.AndroidManifestKeySet);
2056 final String keysetName = sa.getNonResourceString(
2057 com.android.internal.R.styleable.AndroidManifestKeySet_name);
2058 definedKeySets.put(keysetName, new ArraySet<String>());
2059 currentKeySet = keysetName;
2060 currentKeySetDepth = parser.getDepth();
2061 sa.recycle();
2062 } else if (tagName.equals("public-key")) {
2063 if (currentKeySet == null) {
2064 Slog.w(TAG, "Improperly nested 'public-key' tag at "
2065 + parser.getPositionDescription());
2066 return false;
2067 }
2068 final TypedArray sa = res.obtainAttributes(attrs,
2069 com.android.internal.R.styleable.AndroidManifestPublicKey);
2070 final String publicKeyName = sa.getNonResourceString(
2071 com.android.internal.R.styleable.AndroidManifestPublicKey_name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002072 final String encodedKey = sa.getNonResourceString(
dcashman989eb3712014-06-17 12:56:12 -07002073 com.android.internal.R.styleable.AndroidManifestPublicKey_value);
2074 if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
2075 Slog.w(TAG, "'public-key' " + publicKeyName + " must define a public-key value"
2076 + " on first use at " + parser.getPositionDescription());
Kenny Root37dca152013-07-10 14:01:49 -07002077 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002078 return false;
2079 } else if (encodedKey != null) {
2080 PublicKey currentKey = parsePublicKey(encodedKey);
2081 if (currentKey == null) {
2082 Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
2083 + parser.getPositionDescription() + " key-set " + currentKeySet
2084 + " will not be added to the package's defined key-sets.");
2085 sa.recycle();
2086 improperKeySets.add(currentKeySet);
2087 XmlUtils.skipCurrentTag(parser);
2088 continue;
2089 }
2090 if (publicKeys.get(publicKeyName) == null
2091 || publicKeys.get(publicKeyName).equals(currentKey)) {
2092
2093 /* public-key first definition, or matches old definition */
2094 publicKeys.put(publicKeyName, currentKey);
2095 } else {
2096 Slog.w(TAG, "Value of 'public-key' " + publicKeyName
2097 + " conflicts with previously defined value at "
2098 + parser.getPositionDescription());
2099 sa.recycle();
2100 return false;
2101 }
Kenny Root37dca152013-07-10 14:01:49 -07002102 }
dcashman989eb3712014-06-17 12:56:12 -07002103 definedKeySets.get(currentKeySet).add(publicKeyName);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002104 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002105 XmlUtils.skipCurrentTag(parser);
2106 } else if (tagName.equals("upgrade-key-set")) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08002107 final TypedArray sa = res.obtainAttributes(attrs,
dcashman989eb3712014-06-17 12:56:12 -07002108 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
2109 String name = sa.getNonResourceString(
2110 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
2111 upgradeKeySets.add(name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002112 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002113 XmlUtils.skipCurrentTag(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002114 } else if (RIGID_PARSER) {
dcashman989eb3712014-06-17 12:56:12 -07002115 Slog.w(TAG, "Bad element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08002116 + " at " + mArchiveSourcePath + " "
2117 + parser.getPositionDescription());
2118 return false;
2119 } else {
dcashman989eb3712014-06-17 12:56:12 -07002120 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08002121 + " at " + mArchiveSourcePath + " "
2122 + parser.getPositionDescription());
2123 XmlUtils.skipCurrentTag(parser);
2124 continue;
2125 }
2126 }
dcashman989eb3712014-06-17 12:56:12 -07002127 Set<String> publicKeyNames = publicKeys.keySet();
2128 if (publicKeyNames.removeAll(definedKeySets.keySet())) {
2129 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
2130 + "'key-set' and 'public-key' names must be distinct.");
2131 return false;
2132 }
2133 owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
2134 for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) {
2135 final String keySetName = e.getKey();
2136 if (e.getValue().size() == 0) {
2137 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
2138 + "'key-set' " + keySetName + " has no valid associated 'public-key'."
2139 + " Not including in package's defined key-sets.");
2140 continue;
2141 } else if (improperKeySets.contains(keySetName)) {
2142 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
2143 + "'key-set' " + keySetName + " contained improper 'public-key'"
2144 + " tags. Not including in package's defined key-sets.");
2145 continue;
2146 }
2147 owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
2148 for (String s : e.getValue()) {
2149 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
Geremy Condraf1bcca82013-01-07 22:35:24 -08002150 }
2151 }
dcashman989eb3712014-06-17 12:56:12 -07002152 if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
2153 owner.mUpgradeKeySets = upgradeKeySets;
2154 } else {
2155 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
2156 + "does not define all 'upgrade-key-set's .");
2157 return false;
2158 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002159 return true;
2160 }
2161
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07002162 private PermissionGroup parsePermissionGroup(Package owner, int flags, Resources res,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002163 XmlPullParser parser, AttributeSet attrs, String[] outError)
2164 throws XmlPullParserException, IOException {
2165 PermissionGroup perm = new PermissionGroup(owner);
2166
2167 TypedArray sa = res.obtainAttributes(attrs,
2168 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
2169
2170 if (!parsePackageItemInfo(owner, perm.info, outError,
2171 "<permission-group>", sa,
2172 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
2173 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002174 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
Jose Limaf78e3122014-03-06 12:13:15 -08002175 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
2176 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002177 sa.recycle();
2178 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2179 return null;
2180 }
2181
2182 perm.info.descriptionRes = sa.getResourceId(
2183 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
2184 0);
Dianne Hackborn7454d3b2012-09-12 17:22:00 -07002185 perm.info.flags = sa.getInt(
2186 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07002187 perm.info.priority = sa.getInt(
2188 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
Dianne Hackborn99222d22012-05-06 16:30:15 -07002189 if (perm.info.priority > 0 && (flags&PARSE_IS_SYSTEM) == 0) {
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07002190 perm.info.priority = 0;
2191 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192
2193 sa.recycle();
2194
2195 if (!parseAllMetaData(res, parser, attrs, "<permission-group>", perm,
2196 outError)) {
2197 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2198 return null;
2199 }
2200
2201 owner.permissionGroups.add(perm);
2202
2203 return perm;
2204 }
2205
2206 private Permission parsePermission(Package owner, Resources res,
2207 XmlPullParser parser, AttributeSet attrs, String[] outError)
2208 throws XmlPullParserException, IOException {
2209 Permission perm = new Permission(owner);
2210
2211 TypedArray sa = res.obtainAttributes(attrs,
2212 com.android.internal.R.styleable.AndroidManifestPermission);
2213
2214 if (!parsePackageItemInfo(owner, perm.info, outError,
2215 "<permission>", sa,
2216 com.android.internal.R.styleable.AndroidManifestPermission_name,
2217 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002218 com.android.internal.R.styleable.AndroidManifestPermission_icon,
Jose Limaf78e3122014-03-06 12:13:15 -08002219 com.android.internal.R.styleable.AndroidManifestPermission_logo,
2220 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002221 sa.recycle();
2222 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2223 return null;
2224 }
2225
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002226 // Note: don't allow this value to be a reference to a resource
2227 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002228 perm.info.group = sa.getNonResourceString(
2229 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
2230 if (perm.info.group != null) {
2231 perm.info.group = perm.info.group.intern();
2232 }
2233
2234 perm.info.descriptionRes = sa.getResourceId(
2235 com.android.internal.R.styleable.AndroidManifestPermission_description,
2236 0);
2237
2238 perm.info.protectionLevel = sa.getInt(
2239 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
2240 PermissionInfo.PROTECTION_NORMAL);
2241
Dianne Hackborn2ca2c872012-09-16 16:03:36 -07002242 perm.info.flags = sa.getInt(
2243 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
2244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002245 sa.recycle();
Dianne Hackborne639da72012-02-21 15:11:13 -08002246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002247 if (perm.info.protectionLevel == -1) {
2248 outError[0] = "<permission> does not specify protectionLevel";
2249 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2250 return null;
2251 }
Dianne Hackborne639da72012-02-21 15:11:13 -08002252
2253 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
2254
2255 if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_FLAGS) != 0) {
2256 if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
2257 PermissionInfo.PROTECTION_SIGNATURE) {
2258 outError[0] = "<permission> protectionLevel specifies a flag but is "
2259 + "not based on signature type";
2260 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2261 return null;
2262 }
2263 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002264
2265 if (!parseAllMetaData(res, parser, attrs, "<permission>", perm,
2266 outError)) {
2267 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2268 return null;
2269 }
2270
2271 owner.permissions.add(perm);
2272
2273 return perm;
2274 }
2275
2276 private Permission parsePermissionTree(Package owner, Resources res,
2277 XmlPullParser parser, AttributeSet attrs, String[] outError)
2278 throws XmlPullParserException, IOException {
2279 Permission perm = new Permission(owner);
2280
2281 TypedArray sa = res.obtainAttributes(attrs,
2282 com.android.internal.R.styleable.AndroidManifestPermissionTree);
2283
2284 if (!parsePackageItemInfo(owner, perm.info, outError,
2285 "<permission-tree>", sa,
2286 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
2287 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002288 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
Jose Limaf78e3122014-03-06 12:13:15 -08002289 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
2290 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002291 sa.recycle();
2292 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2293 return null;
2294 }
2295
2296 sa.recycle();
2297
2298 int index = perm.info.name.indexOf('.');
2299 if (index > 0) {
2300 index = perm.info.name.indexOf('.', index+1);
2301 }
2302 if (index < 0) {
2303 outError[0] = "<permission-tree> name has less than three segments: "
2304 + perm.info.name;
2305 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2306 return null;
2307 }
2308
2309 perm.info.descriptionRes = 0;
2310 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
2311 perm.tree = true;
2312
2313 if (!parseAllMetaData(res, parser, attrs, "<permission-tree>", perm,
2314 outError)) {
2315 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2316 return null;
2317 }
2318
2319 owner.permissions.add(perm);
2320
2321 return perm;
2322 }
2323
2324 private Instrumentation parseInstrumentation(Package owner, Resources res,
2325 XmlPullParser parser, AttributeSet attrs, String[] outError)
2326 throws XmlPullParserException, IOException {
2327 TypedArray sa = res.obtainAttributes(attrs,
2328 com.android.internal.R.styleable.AndroidManifestInstrumentation);
2329
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002330 if (mParseInstrumentationArgs == null) {
2331 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
2332 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
2333 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002334 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
Jose Limaf78e3122014-03-06 12:13:15 -08002335 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
2336 com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002337 mParseInstrumentationArgs.tag = "<instrumentation>";
2338 }
2339
2340 mParseInstrumentationArgs.sa = sa;
2341
2342 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
2343 new InstrumentationInfo());
2344 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002345 sa.recycle();
2346 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2347 return null;
2348 }
2349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002350 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002351 // Note: don't allow this value to be a reference to a resource
2352 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002353 str = sa.getNonResourceString(
2354 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
2355 a.info.targetPackage = str != null ? str.intern() : null;
2356
2357 a.info.handleProfiling = sa.getBoolean(
2358 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
2359 false);
2360
2361 a.info.functionalTest = sa.getBoolean(
2362 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
2363 false);
2364
2365 sa.recycle();
2366
2367 if (a.info.targetPackage == null) {
2368 outError[0] = "<instrumentation> does not specify targetPackage";
2369 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2370 return null;
2371 }
2372
2373 if (!parseAllMetaData(res, parser, attrs, "<instrumentation>", a,
2374 outError)) {
2375 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2376 return null;
2377 }
2378
2379 owner.instrumentation.add(a);
2380
2381 return a;
2382 }
2383
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002384 /**
2385 * Parse the {@code application} XML tree at the current parse location in a
2386 * <em>base APK</em> manifest.
2387 * <p>
2388 * When adding new features, carefully consider if they should also be
2389 * supported by split APKs.
2390 */
2391 private boolean parseBaseApplication(Package owner, Resources res,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002392 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
2393 throws XmlPullParserException, IOException {
2394 final ApplicationInfo ai = owner.applicationInfo;
2395 final String pkgName = owner.applicationInfo.packageName;
2396
2397 TypedArray sa = res.obtainAttributes(attrs,
2398 com.android.internal.R.styleable.AndroidManifestApplication);
2399
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002400 String name = sa.getNonConfigurationString(
2401 com.android.internal.R.styleable.AndroidManifestApplication_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002402 if (name != null) {
2403 ai.className = buildClassName(pkgName, name, outError);
2404 if (ai.className == null) {
2405 sa.recycle();
2406 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2407 return false;
2408 }
2409 }
2410
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002411 String manageSpaceActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002412 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
2413 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002414 if (manageSpaceActivity != null) {
2415 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
2416 outError);
2417 }
2418
Christopher Tate181fafa2009-05-14 11:12:14 -07002419 boolean allowBackup = sa.getBoolean(
2420 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
2421 if (allowBackup) {
2422 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07002423
Christopher Tate3de55bc2010-03-12 17:28:08 -08002424 // backupAgent, killAfterRestore, and restoreAnyVersion are only relevant
2425 // if backup is possible for the given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002426 String backupAgent = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002427 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
2428 Configuration.NATIVE_CONFIG_VERSION);
Christopher Tate181fafa2009-05-14 11:12:14 -07002429 if (backupAgent != null) {
2430 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07002431 if (DEBUG_BACKUP) {
2432 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002433 + " from " + pkgName + "+" + backupAgent);
2434 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07002435
2436 if (sa.getBoolean(
2437 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
2438 true)) {
2439 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
2440 }
2441 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08002442 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
2443 false)) {
2444 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
2445 }
Christopher Tated1de2562014-06-17 17:12:35 -07002446 if (sa.getBoolean(
2447 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
2448 false)) {
2449 ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
2450 }
Christopher Tate181fafa2009-05-14 11:12:14 -07002451 }
2452 }
Christopher Tate4a627c72011-04-01 14:43:32 -07002453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002454 TypedValue v = sa.peekValue(
2455 com.android.internal.R.styleable.AndroidManifestApplication_label);
2456 if (v != null && (ai.labelRes=v.resourceId) == 0) {
2457 ai.nonLocalizedLabel = v.coerceToString();
2458 }
2459
2460 ai.icon = sa.getResourceId(
2461 com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
Adam Powell81cd2e92010-04-21 16:35:18 -07002462 ai.logo = sa.getResourceId(
2463 com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);
Jose Limaf78e3122014-03-06 12:13:15 -08002464 ai.banner = sa.getResourceId(
2465 com.android.internal.R.styleable.AndroidManifestApplication_banner, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002466 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08002467 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002468 ai.descriptionRes = sa.getResourceId(
2469 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
2470
2471 if ((flags&PARSE_IS_SYSTEM) != 0) {
2472 if (sa.getBoolean(
2473 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
2474 false)) {
2475 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
2476 }
Amith Yamasani0d8750d2013-05-01 15:25:28 -07002477 }
2478
2479 if (sa.getBoolean(
2480 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
2481 false)) {
2482 owner.mRequiredForAllUsers = true;
Amith Yamasanie993ae12013-04-15 13:42:57 -07002483 }
2484
2485 String restrictedAccountType = sa.getString(com.android.internal.R.styleable
2486 .AndroidManifestApplication_restrictedAccountType);
2487 if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
2488 owner.mRestrictedAccountType = restrictedAccountType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002489 }
2490
Amith Yamasaniccbe3892013-04-12 17:52:42 -07002491 String requiredAccountType = sa.getString(com.android.internal.R.styleable
2492 .AndroidManifestApplication_requiredAccountType);
2493 if (requiredAccountType != null && requiredAccountType.length() > 0) {
2494 owner.mRequiredAccountType = requiredAccountType;
2495 }
2496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002497 if (sa.getBoolean(
2498 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
2499 false)) {
2500 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
2501 }
2502
2503 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07002504 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08002505 false)) {
2506 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
2507 }
2508
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002509 owner.baseHardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07002510 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07002511 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Alan Viverette9b0ab652015-03-18 14:21:04 -07002512 ai.hardwareAccelerated = owner.baseHardwareAccelerated;
Romain Guy812ccbe2010-06-01 14:07:24 -07002513
2514 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002515 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
2516 true)) {
2517 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
2518 }
2519
2520 if (sa.getBoolean(
2521 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
2522 false)) {
2523 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
2524 }
2525
2526 if (sa.getBoolean(
2527 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
2528 true)) {
2529 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
2530 }
2531
Dianne Hackbornade3eca2009-05-11 18:54:45 -07002532 if (sa.getBoolean(
2533 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
Dianne Hackborne7fe35b2009-05-13 10:53:41 -07002534 false)) {
Dianne Hackbornade3eca2009-05-11 18:54:45 -07002535 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
2536 }
2537
Jason parksa3cdaa52011-01-13 14:15:43 -06002538 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08002539 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06002540 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08002541 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06002542 }
2543
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07002544 if (sa.getBoolean(
Alex Klyubin01a959d2015-03-18 10:05:45 -07002545 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
2546 true)) {
2547 ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
2548 }
2549
2550 if (sa.getBoolean(
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07002551 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
2552 false /* default is no RTL support*/)) {
2553 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
2554 }
2555
Narayan Kamath589a1bc2014-07-03 14:43:26 +01002556 if (sa.getBoolean(
2557 com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
2558 false)) {
2559 ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
2560 }
2561
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07002562 if (sa.getBoolean(
2563 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
2564 true)) {
2565 ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
2566 }
2567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002568 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002569 str = sa.getNonConfigurationString(
2570 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002571 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
2572
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002573 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
2574 str = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002575 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
2576 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002577 } else {
2578 // Some older apps have been seen to use a resource reference
2579 // here that on older builds was ignored (with a warning). We
2580 // need to continue to do this for them so they don't break.
2581 str = sa.getNonResourceString(
2582 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
2583 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002584 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
2585 str, outError);
2586
2587 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002588 CharSequence pname;
2589 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
2590 pname = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002591 com.android.internal.R.styleable.AndroidManifestApplication_process,
2592 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002593 } else {
2594 // Some older apps have been seen to use a resource reference
2595 // here that on older builds was ignored (with a warning). We
2596 // need to continue to do this for them so they don't break.
2597 pname = sa.getNonResourceString(
2598 com.android.internal.R.styleable.AndroidManifestApplication_process);
2599 }
2600 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002601 flags, mSeparateProcesses, outError);
2602
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002603 ai.enabled = sa.getBoolean(
2604 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002605
Jose Lima12d0b4c2014-03-14 16:55:12 -07002606 if (sa.getBoolean(
2607 com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
2608 ai.flags |= ApplicationInfo.FLAG_IS_GAME;
2609 }
2610
Dianne Hackborn02486b12010-08-26 14:18:37 -07002611 if (false) {
2612 if (sa.getBoolean(
2613 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
2614 false)) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08002615 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07002616
2617 // A heavy-weight application can not be in a custom process.
2618 // We can do direct compare because we intern all strings.
2619 if (ai.processName != null && ai.processName != ai.packageName) {
2620 outError[0] = "cantSaveState applications can not use custom processes";
2621 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07002622 }
2623 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002624 }
2625
Adam Powell269248d2011-08-02 10:26:54 -07002626 ai.uiOptions = sa.getInt(
2627 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
2628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 sa.recycle();
2630
2631 if (outError[0] != null) {
2632 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2633 return false;
2634 }
2635
2636 final int innerDepth = parser.getDepth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002637 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07002638 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2639 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
2640 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002641 continue;
2642 }
2643
2644 String tagName = parser.getName();
2645 if (tagName.equals("activity")) {
Romain Guy529b60a2010-08-03 18:05:47 -07002646 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002647 owner.baseHardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002648 if (a == null) {
2649 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2650 return false;
2651 }
2652
2653 owner.activities.add(a);
2654
2655 } else if (tagName.equals("receiver")) {
Romain Guy529b60a2010-08-03 18:05:47 -07002656 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002657 if (a == null) {
2658 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2659 return false;
2660 }
2661
2662 owner.receivers.add(a);
2663
2664 } else if (tagName.equals("service")) {
2665 Service s = parseService(owner, res, parser, attrs, flags, outError);
2666 if (s == null) {
2667 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2668 return false;
2669 }
2670
2671 owner.services.add(s);
2672
2673 } else if (tagName.equals("provider")) {
2674 Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
2675 if (p == null) {
2676 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2677 return false;
2678 }
2679
2680 owner.providers.add(p);
2681
2682 } else if (tagName.equals("activity-alias")) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002683 Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002684 if (a == null) {
2685 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2686 return false;
2687 }
2688
2689 owner.activities.add(a);
2690
2691 } else if (parser.getName().equals("meta-data")) {
2692 // note: application meta-data is stored off to the side, so it can
2693 // remain null in the primary copy (we like to avoid extra copies because
2694 // it can be large)
2695 if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData,
2696 outError)) == null) {
2697 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2698 return false;
2699 }
2700
Dianne Hackbornc895be72013-03-11 17:48:43 -07002701 } else if (tagName.equals("library")) {
2702 sa = res.obtainAttributes(attrs,
2703 com.android.internal.R.styleable.AndroidManifestLibrary);
2704
2705 // Note: don't allow this value to be a reference to a resource
2706 // that may change.
2707 String lname = sa.getNonResourceString(
2708 com.android.internal.R.styleable.AndroidManifestLibrary_name);
2709
2710 sa.recycle();
2711
2712 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002713 lname = lname.intern();
2714 if (!ArrayUtils.contains(owner.libraryNames, lname)) {
2715 owner.libraryNames = ArrayUtils.add(owner.libraryNames, lname);
Dianne Hackbornc895be72013-03-11 17:48:43 -07002716 }
2717 }
2718
2719 XmlUtils.skipCurrentTag(parser);
2720
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002721 } else if (tagName.equals("uses-library")) {
2722 sa = res.obtainAttributes(attrs,
2723 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
2724
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002725 // Note: don't allow this value to be a reference to a resource
2726 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 String lname = sa.getNonResourceString(
2728 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07002729 boolean req = sa.getBoolean(
2730 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
2731 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002732
2733 sa.recycle();
2734
Dianne Hackborn49237342009-08-27 20:08:01 -07002735 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002736 lname = lname.intern();
Dianne Hackborn49237342009-08-27 20:08:01 -07002737 if (req) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002738 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07002739 } else {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002740 owner.usesOptionalLibraries = ArrayUtils.add(
2741 owner.usesOptionalLibraries, lname);
2742 }
2743 }
2744
2745 XmlUtils.skipCurrentTag(parser);
2746
2747 } else if (tagName.equals("uses-package")) {
2748 // Dependencies for app installers; we don't currently try to
2749 // enforce this.
2750 XmlUtils.skipCurrentTag(parser);
2751
2752 } else {
2753 if (!RIGID_PARSER) {
2754 Slog.w(TAG, "Unknown element under <application>: " + tagName
2755 + " at " + mArchiveSourcePath + " "
2756 + parser.getPositionDescription());
2757 XmlUtils.skipCurrentTag(parser);
2758 continue;
2759 } else {
2760 outError[0] = "Bad element under <application>: " + tagName;
2761 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2762 return false;
2763 }
2764 }
2765 }
2766
Narayan Kamathb12dcfb2015-03-30 11:31:04 +01002767 modifySharedLibrariesForBackwardCompatibility(owner);
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00002768
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07002769 if (hasDomainURLs(owner)) {
2770 owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
2771 } else {
2772 owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
2773 }
2774
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002775 return true;
2776 }
2777
Narayan Kamathb12dcfb2015-03-30 11:31:04 +01002778 private static void modifySharedLibrariesForBackwardCompatibility(Package owner) {
2779 // "org.apache.http.legacy" is now a part of the boot classpath so it doesn't need
2780 // to be an explicit dependency.
2781 //
2782 // A future change will remove this library from the boot classpath, at which point
2783 // all apps that target SDK 21 and earlier will have it automatically added to their
2784 // dependency lists.
2785 owner.usesLibraries = ArrayUtils.remove(owner.usesLibraries, "org.apache.http.legacy");
2786 owner.usesOptionalLibraries = ArrayUtils.remove(owner.usesOptionalLibraries,
2787 "org.apache.http.legacy");
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00002788 }
2789
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002790 /**
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07002791 * 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 -07002792 */
2793 private static boolean hasDomainURLs(Package pkg) {
2794 if (pkg == null || pkg.activities == null) return false;
2795 final ArrayList<Activity> activities = pkg.activities;
2796 final int countActivities = activities.size();
2797 for (int n=0; n<countActivities; n++) {
2798 Activity activity = activities.get(n);
2799 ArrayList<ActivityIntentInfo> filters = activity.intents;
2800 if (filters == null) continue;
2801 final int countFilters = filters.size();
2802 for (int m=0; m<countFilters; m++) {
2803 ActivityIntentInfo aii = filters.get(m);
2804 if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07002805 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07002806 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
2807 aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
Fabrice Di Meglio7d014ce2015-04-08 16:17:46 -07002808 Slog.d(TAG, "hasDomainURLs:true for package:" + pkg.packageName);
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07002809 return true;
2810 }
2811 }
2812 }
2813 return false;
2814 }
2815
2816 /**
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002817 * Parse the {@code application} XML tree at the current parse location in a
2818 * <em>split APK</em> manifest.
2819 * <p>
2820 * Note that split APKs have many more restrictions on what they're capable
2821 * of doing, so many valid features of a base APK have been carefully
2822 * omitted here.
2823 */
2824 private boolean parseSplitApplication(Package owner, Resources res, XmlPullParser parser,
2825 AttributeSet attrs, int flags, int splitIndex, String[] outError)
2826 throws XmlPullParserException, IOException {
2827 TypedArray sa = res.obtainAttributes(attrs,
2828 com.android.internal.R.styleable.AndroidManifestApplication);
2829
2830 if (sa.getBoolean(
2831 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
2832 owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
2833 }
2834
2835 final int innerDepth = parser.getDepth();
2836 int type;
2837 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2838 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
2839 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2840 continue;
2841 }
2842
2843 String tagName = parser.getName();
2844 if (tagName.equals("activity")) {
2845 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
2846 owner.baseHardwareAccelerated);
2847 if (a == null) {
2848 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2849 return false;
2850 }
2851
2852 owner.activities.add(a);
2853
2854 } else if (tagName.equals("receiver")) {
2855 Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
2856 if (a == null) {
2857 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2858 return false;
2859 }
2860
2861 owner.receivers.add(a);
2862
2863 } else if (tagName.equals("service")) {
2864 Service s = parseService(owner, res, parser, attrs, flags, outError);
2865 if (s == null) {
2866 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2867 return false;
2868 }
2869
2870 owner.services.add(s);
2871
2872 } else if (tagName.equals("provider")) {
2873 Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
2874 if (p == null) {
2875 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2876 return false;
2877 }
2878
2879 owner.providers.add(p);
2880
2881 } else if (tagName.equals("activity-alias")) {
2882 Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
2883 if (a == null) {
2884 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2885 return false;
2886 }
2887
2888 owner.activities.add(a);
2889
2890 } else if (parser.getName().equals("meta-data")) {
2891 // note: application meta-data is stored off to the side, so it can
2892 // remain null in the primary copy (we like to avoid extra copies because
2893 // it can be large)
2894 if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData,
2895 outError)) == null) {
2896 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2897 return false;
2898 }
2899
2900 } else if (tagName.equals("uses-library")) {
2901 sa = res.obtainAttributes(attrs,
2902 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
2903
2904 // Note: don't allow this value to be a reference to a resource
2905 // that may change.
2906 String lname = sa.getNonResourceString(
2907 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
2908 boolean req = sa.getBoolean(
2909 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
2910 true);
2911
2912 sa.recycle();
2913
2914 if (lname != null) {
2915 lname = lname.intern();
2916 if (req) {
2917 // Upgrade to treat as stronger constraint
2918 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
2919 owner.usesOptionalLibraries = ArrayUtils.remove(
2920 owner.usesOptionalLibraries, lname);
2921 } else {
2922 // Ignore if someone already defined as required
2923 if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
2924 owner.usesOptionalLibraries = ArrayUtils.add(
2925 owner.usesOptionalLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07002926 }
2927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002928 }
2929
2930 XmlUtils.skipCurrentTag(parser);
2931
Dianne Hackborncef65ee2010-09-30 18:27:22 -07002932 } else if (tagName.equals("uses-package")) {
2933 // Dependencies for app installers; we don't currently try to
2934 // enforce this.
2935 XmlUtils.skipCurrentTag(parser);
2936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002937 } else {
2938 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002939 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002940 + " at " + mArchiveSourcePath + " "
2941 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002942 XmlUtils.skipCurrentTag(parser);
2943 continue;
2944 } else {
2945 outError[0] = "Bad element under <application>: " + tagName;
2946 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2947 return false;
2948 }
2949 }
2950 }
2951
2952 return true;
2953 }
2954
2955 private boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
2956 String[] outError, String tag, TypedArray sa,
Jose Limaf78e3122014-03-06 12:13:15 -08002957 int nameRes, int labelRes, int iconRes, int logoRes, int bannerRes) {
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002958 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002959 if (name == null) {
2960 outError[0] = tag + " does not specify android:name";
2961 return false;
2962 }
2963
2964 outInfo.name
2965 = buildClassName(owner.applicationInfo.packageName, name, outError);
2966 if (outInfo.name == null) {
2967 return false;
2968 }
2969
2970 int iconVal = sa.getResourceId(iconRes, 0);
2971 if (iconVal != 0) {
2972 outInfo.icon = iconVal;
2973 outInfo.nonLocalizedLabel = null;
2974 }
Adam Powell81cd2e92010-04-21 16:35:18 -07002975
2976 int logoVal = sa.getResourceId(logoRes, 0);
2977 if (logoVal != 0) {
2978 outInfo.logo = logoVal;
2979 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002980
Jose Limaf78e3122014-03-06 12:13:15 -08002981 int bannerVal = sa.getResourceId(bannerRes, 0);
2982 if (bannerVal != 0) {
2983 outInfo.banner = bannerVal;
2984 }
2985
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002986 TypedValue v = sa.peekValue(labelRes);
2987 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
2988 outInfo.nonLocalizedLabel = v.coerceToString();
2989 }
2990
2991 outInfo.packageName = owner.packageName;
2992
2993 return true;
2994 }
2995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002996 private Activity parseActivity(Package owner, Resources res,
2997 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError,
Romain Guy529b60a2010-08-03 18:05:47 -07002998 boolean receiver, boolean hardwareAccelerated)
2999 throws XmlPullParserException, IOException {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003000 TypedArray sa = res.obtainAttributes(attrs, R.styleable.AndroidManifestActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003001
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003002 if (mParseActivityArgs == null) {
3003 mParseActivityArgs = new ParseComponentArgs(owner, outError,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003004 R.styleable.AndroidManifestActivity_name,
3005 R.styleable.AndroidManifestActivity_label,
3006 R.styleable.AndroidManifestActivity_icon,
3007 R.styleable.AndroidManifestActivity_logo,
3008 R.styleable.AndroidManifestActivity_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003009 mSeparateProcesses,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003010 R.styleable.AndroidManifestActivity_process,
3011 R.styleable.AndroidManifestActivity_description,
3012 R.styleable.AndroidManifestActivity_enabled);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003013 }
3014
3015 mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
3016 mParseActivityArgs.sa = sa;
3017 mParseActivityArgs.flags = flags;
3018
3019 Activity a = new Activity(mParseActivityArgs, new ActivityInfo());
3020 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003021 sa.recycle();
3022 return null;
3023 }
3024
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003025 boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003026 if (setExported) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003027 a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003028 }
3029
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003030 a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003031
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003032 a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
Adam Powell269248d2011-08-02 10:26:54 -07003033 a.info.applicationInfo.uiOptions);
3034
Adam Powelldd8fab22012-03-22 17:47:27 -07003035 String parentName = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003036 R.styleable.AndroidManifestActivity_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003037 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07003038 if (parentName != null) {
3039 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
3040 if (outError[0] == null) {
3041 a.info.parentActivityName = parentClassName;
3042 } else {
3043 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
3044 parentName);
3045 outError[0] = null;
3046 }
3047 }
3048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003049 String str;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003050 str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051 if (str == null) {
3052 a.info.permission = owner.applicationInfo.permission;
3053 } else {
3054 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
3055 }
3056
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003057 str = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003058 R.styleable.AndroidManifestActivity_taskAffinity,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003059 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003060 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
3061 owner.applicationInfo.taskAffinity, str, outError);
3062
3063 a.info.flags = 0;
3064 if (sa.getBoolean(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003065 R.styleable.AndroidManifestActivity_multiprocess, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
3067 }
3068
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003069 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003070 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
3071 }
3072
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003073 if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003074 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
3075 }
3076
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003077 if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003078 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
3079 }
3080
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003081 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003082 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
3083 }
3084
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003085 if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
3087 }
3088
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003089 if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003090 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
3091 }
3092
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003093 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003094 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
3095 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
3096 }
3097
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003098 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
Dianne Hackbornffa42482009-09-23 22:20:11 -07003099 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
3100 }
3101
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003102 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)) {
Craig Mautner5962b122012-10-05 14:45:52 -07003103 a.info.flags |= ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN;
3104 }
3105
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003106 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
Daniel Sandler613dde42010-06-21 13:46:39 -04003107 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
3108 }
Craig Mautner5962b122012-10-05 14:45:52 -07003109
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003110 if (sa.getBoolean(R.styleable.AndroidManifestActivity_primaryUserOnly, false)) {
Fyodor Kupolov703d1c42015-01-27 11:59:00 -08003111 a.info.flags |= ActivityInfo.FLAG_PRIMARY_USER_ONLY;
3112 }
3113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003114 if (!receiver) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003115 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07003116 hardwareAccelerated)) {
3117 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
3118 }
3119
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003120 a.info.launchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003121 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
Craig Mautner2dac0562014-05-06 09:06:44 -07003122 a.info.documentLaunchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003123 R.styleable.AndroidManifestActivity_documentLaunchMode,
Craig Mautner2dac0562014-05-06 09:06:44 -07003124 ActivityInfo.DOCUMENT_LAUNCH_NONE);
Craig Mautnerffcfcaa2014-06-05 09:54:38 -07003125 a.info.maxRecents = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003126 R.styleable.AndroidManifestActivity_maxRecents,
Dianne Hackborn852975d2014-08-22 17:42:43 -07003127 ActivityManager.getDefaultAppRecentsLimitStatic());
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003128 a.info.configChanges = sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003129 a.info.softInputMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003130 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
Craig Mautner2dac0562014-05-06 09:06:44 -07003131
Craig Mautner43e52ed2014-06-16 17:18:52 -07003132 a.info.persistableMode = sa.getInteger(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003133 R.styleable.AndroidManifestActivity_persistableMode,
Craig Mautner43e52ed2014-06-16 17:18:52 -07003134 ActivityInfo.PERSIST_ROOT_ONLY);
Craig Mautner2dac0562014-05-06 09:06:44 -07003135
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003136 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07003137 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
3138 }
3139
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003140 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07003141 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
3142 }
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07003143
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003144 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07003145 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
3146 }
Dianne Hackborna4e102e2014-09-04 22:52:27 -07003147
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003148 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
Dianne Hackborna4e102e2014-09-04 22:52:27 -07003149 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
3150 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003151
3152 a.info.resizeable = sa.getBoolean(
Wale Ogunwaleabfcc222015-03-20 11:32:20 -07003153 R.styleable.AndroidManifestActivity_resizeableActivity, false);
Wale Ogunwalea9281272015-02-07 14:04:19 -08003154 if (a.info.resizeable) {
3155 // Fixed screen orientation isn't supported with resizeable activities.
3156 a.info.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3157 } else {
3158 a.info.screenOrientation = sa.getInt(
3159 R.styleable.AndroidManifestActivity_screenOrientation,
3160 ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
3161 }
Craig Mautner15df08a2015-04-01 12:17:18 -07003162
3163 a.info.lockTaskLaunchMode =
3164 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003165 } else {
3166 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
3167 a.info.configChanges = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003168
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003169 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07003170 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003171 if (a.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003172 Slog.w(TAG, "Activity exported request ignored due to singleUser: "
3173 + a.className + " at " + mArchiveSourcePath + " "
3174 + parser.getPositionDescription());
3175 a.info.exported = false;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003176 setExported = true;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003177 }
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003178 }
3179 }
3180
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003181 sa.recycle();
3182
Alex Klyubinb9f8a522015-02-03 11:12:59 -08003183 if (receiver && (owner.applicationInfo.privateFlags
3184 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07003185 // A heavy-weight application can not have receives in its main process
3186 // We can do direct compare because we intern all strings.
3187 if (a.info.processName == owner.packageName) {
3188 outError[0] = "Heavy-weight applications can not have receivers in main process";
3189 }
3190 }
3191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003192 if (outError[0] != null) {
3193 return null;
3194 }
3195
3196 int outerDepth = parser.getDepth();
3197 int type;
3198 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3199 && (type != XmlPullParser.END_TAG
3200 || parser.getDepth() > outerDepth)) {
3201 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3202 continue;
3203 }
3204
3205 if (parser.getName().equals("intent-filter")) {
3206 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08003207 if (!parseIntent(res, parser, attrs, true, true, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003208 return null;
3209 }
3210 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003211 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07003212 + mArchiveSourcePath + " "
3213 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003214 } else {
3215 a.intents.add(intent);
3216 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07003217 } else if (!receiver && parser.getName().equals("preferred")) {
3218 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08003219 if (!parseIntent(res, parser, attrs, false, false, intent, outError)) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07003220 return null;
3221 }
3222 if (intent.countActions() == 0) {
3223 Slog.w(TAG, "No actions in preferred at "
3224 + mArchiveSourcePath + " "
3225 + parser.getPositionDescription());
3226 } else {
3227 if (owner.preferredActivityFilters == null) {
3228 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
3229 }
3230 owner.preferredActivityFilters.add(intent);
3231 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003232 } else if (parser.getName().equals("meta-data")) {
3233 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
3234 outError)) == null) {
3235 return null;
3236 }
3237 } else {
3238 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003239 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003240 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003241 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003242 + " at " + mArchiveSourcePath + " "
3243 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003244 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07003245 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003246 + " at " + mArchiveSourcePath + " "
3247 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248 }
3249 XmlUtils.skipCurrentTag(parser);
3250 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003251 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07003252 if (receiver) {
3253 outError[0] = "Bad element under <receiver>: " + parser.getName();
3254 } else {
3255 outError[0] = "Bad element under <activity>: " + parser.getName();
3256 }
3257 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003258 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003259 }
3260 }
3261
3262 if (!setExported) {
3263 a.info.exported = a.intents.size() > 0;
3264 }
3265
3266 return a;
3267 }
3268
3269 private Activity parseActivityAlias(Package owner, Resources res,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003270 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
3271 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003272 TypedArray sa = res.obtainAttributes(attrs,
3273 com.android.internal.R.styleable.AndroidManifestActivityAlias);
3274
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003275 String targetActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003276 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
3277 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003278 if (targetActivity == null) {
3279 outError[0] = "<activity-alias> does not specify android:targetActivity";
3280 sa.recycle();
3281 return null;
3282 }
3283
3284 targetActivity = buildClassName(owner.applicationInfo.packageName,
3285 targetActivity, outError);
3286 if (targetActivity == null) {
3287 sa.recycle();
3288 return null;
3289 }
3290
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003291 if (mParseActivityAliasArgs == null) {
3292 mParseActivityAliasArgs = new ParseComponentArgs(owner, outError,
3293 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
3294 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
3295 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07003296 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08003297 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003298 mSeparateProcesses,
3299 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003300 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003301 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
3302 mParseActivityAliasArgs.tag = "<activity-alias>";
3303 }
3304
3305 mParseActivityAliasArgs.sa = sa;
3306 mParseActivityAliasArgs.flags = flags;
3307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003308 Activity target = null;
3309
3310 final int NA = owner.activities.size();
3311 for (int i=0; i<NA; i++) {
3312 Activity t = owner.activities.get(i);
3313 if (targetActivity.equals(t.info.name)) {
3314 target = t;
3315 break;
3316 }
3317 }
3318
3319 if (target == null) {
3320 outError[0] = "<activity-alias> target activity " + targetActivity
3321 + " not found in manifest";
3322 sa.recycle();
3323 return null;
3324 }
3325
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003326 ActivityInfo info = new ActivityInfo();
3327 info.targetActivity = targetActivity;
3328 info.configChanges = target.info.configChanges;
3329 info.flags = target.info.flags;
3330 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07003331 info.logo = target.info.logo;
Jose Limaf78e3122014-03-06 12:13:15 -08003332 info.banner = target.info.banner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003333 info.labelRes = target.info.labelRes;
3334 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
3335 info.launchMode = target.info.launchMode;
3336 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003337 if (info.descriptionRes == 0) {
3338 info.descriptionRes = target.info.descriptionRes;
3339 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003340 info.screenOrientation = target.info.screenOrientation;
3341 info.taskAffinity = target.info.taskAffinity;
3342 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07003343 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07003344 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07003345 info.parentActivityName = target.info.parentActivityName;
Craig Mautner8307ea72014-09-11 15:03:53 -07003346 info.maxRecents = target.info.maxRecents;
3347
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003348 Activity a = new Activity(mParseActivityAliasArgs, info);
3349 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003350 sa.recycle();
3351 return null;
3352 }
3353
3354 final boolean setExported = sa.hasValue(
3355 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
3356 if (setExported) {
3357 a.info.exported = sa.getBoolean(
3358 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
3359 }
3360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003361 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003362 str = sa.getNonConfigurationString(
3363 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003364 if (str != null) {
3365 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
3366 }
3367
Adam Powelldd8fab22012-03-22 17:47:27 -07003368 String parentName = sa.getNonConfigurationString(
3369 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003370 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07003371 if (parentName != null) {
3372 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
3373 if (outError[0] == null) {
3374 a.info.parentActivityName = parentClassName;
3375 } else {
3376 Log.e(TAG, "Activity alias " + a.info.name +
3377 " specified invalid parentActivityName " + parentName);
3378 outError[0] = null;
3379 }
3380 }
3381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003382 sa.recycle();
3383
3384 if (outError[0] != null) {
3385 return null;
3386 }
3387
3388 int outerDepth = parser.getDepth();
3389 int type;
3390 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3391 && (type != XmlPullParser.END_TAG
3392 || parser.getDepth() > outerDepth)) {
3393 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3394 continue;
3395 }
3396
3397 if (parser.getName().equals("intent-filter")) {
3398 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08003399 if (!parseIntent(res, parser, attrs, true, true, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003400 return null;
3401 }
3402 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003403 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07003404 + mArchiveSourcePath + " "
3405 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003406 } else {
3407 a.intents.add(intent);
3408 }
3409 } else if (parser.getName().equals("meta-data")) {
3410 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
3411 outError)) == null) {
3412 return null;
3413 }
3414 } else {
3415 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003416 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003417 + " at " + mArchiveSourcePath + " "
3418 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003419 XmlUtils.skipCurrentTag(parser);
3420 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003421 } else {
3422 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
3423 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003425 }
3426 }
3427
3428 if (!setExported) {
3429 a.info.exported = a.intents.size() > 0;
3430 }
3431
3432 return a;
3433 }
3434
3435 private Provider parseProvider(Package owner, Resources res,
3436 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
3437 throws XmlPullParserException, IOException {
3438 TypedArray sa = res.obtainAttributes(attrs,
3439 com.android.internal.R.styleable.AndroidManifestProvider);
3440
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003441 if (mParseProviderArgs == null) {
3442 mParseProviderArgs = new ParseComponentArgs(owner, outError,
3443 com.android.internal.R.styleable.AndroidManifestProvider_name,
3444 com.android.internal.R.styleable.AndroidManifestProvider_label,
3445 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07003446 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08003447 com.android.internal.R.styleable.AndroidManifestProvider_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003448 mSeparateProcesses,
3449 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003450 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003451 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
3452 mParseProviderArgs.tag = "<provider>";
3453 }
3454
3455 mParseProviderArgs.sa = sa;
3456 mParseProviderArgs.flags = flags;
3457
3458 Provider p = new Provider(mParseProviderArgs, new ProviderInfo());
3459 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 sa.recycle();
3461 return null;
3462 }
3463
Nick Kralevichf097b162012-07-28 12:43:48 -07003464 boolean providerExportedDefault = false;
3465
3466 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
3467 // For compatibility, applications targeting API level 16 or lower
3468 // should have their content providers exported by default, unless they
3469 // specify otherwise.
3470 providerExportedDefault = true;
3471 }
3472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003473 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07003474 com.android.internal.R.styleable.AndroidManifestProvider_exported,
3475 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003476
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003477 String cpname = sa.getNonConfigurationString(
3478 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479
3480 p.info.isSyncable = sa.getBoolean(
3481 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
3482 false);
3483
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003484 String permission = sa.getNonConfigurationString(
3485 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
3486 String str = sa.getNonConfigurationString(
3487 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003488 if (str == null) {
3489 str = permission;
3490 }
3491 if (str == null) {
3492 p.info.readPermission = owner.applicationInfo.permission;
3493 } else {
3494 p.info.readPermission =
3495 str.length() > 0 ? str.toString().intern() : null;
3496 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003497 str = sa.getNonConfigurationString(
3498 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003499 if (str == null) {
3500 str = permission;
3501 }
3502 if (str == null) {
3503 p.info.writePermission = owner.applicationInfo.permission;
3504 } else {
3505 p.info.writePermission =
3506 str.length() > 0 ? str.toString().intern() : null;
3507 }
3508
3509 p.info.grantUriPermissions = sa.getBoolean(
3510 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
3511 false);
3512
3513 p.info.multiprocess = sa.getBoolean(
3514 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
3515 false);
3516
3517 p.info.initOrder = sa.getInt(
3518 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
3519 0);
3520
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003521 p.info.flags = 0;
3522
3523 if (sa.getBoolean(
3524 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
3525 false)) {
3526 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003527 if (p.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003528 Slog.w(TAG, "Provider exported request ignored due to singleUser: "
3529 + p.className + " at " + mArchiveSourcePath + " "
3530 + parser.getPositionDescription());
3531 p.info.exported = false;
3532 }
3533 }
3534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003535 sa.recycle();
3536
Alex Klyubinb9f8a522015-02-03 11:12:59 -08003537 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
3538 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07003539 // A heavy-weight application can not have providers in its main process
3540 // We can do direct compare because we intern all strings.
3541 if (p.info.processName == owner.packageName) {
3542 outError[0] = "Heavy-weight applications can not have providers in main process";
3543 return null;
3544 }
3545 }
3546
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003547 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07003548 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003549 return null;
3550 }
Dianne Hackborn1bc177c2014-12-03 10:20:30 -08003551 if (cpname.length() <= 0) {
3552 outError[0] = "<provider> has empty authorities attribute";
3553 return null;
3554 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003555 p.info.authority = cpname.intern();
3556
3557 if (!parseProviderTags(res, parser, attrs, p, outError)) {
3558 return null;
3559 }
3560
3561 return p;
3562 }
3563
3564 private boolean parseProviderTags(Resources res,
3565 XmlPullParser parser, AttributeSet attrs,
3566 Provider outInfo, String[] outError)
3567 throws XmlPullParserException, IOException {
3568 int outerDepth = parser.getDepth();
3569 int type;
3570 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3571 && (type != XmlPullParser.END_TAG
3572 || parser.getDepth() > outerDepth)) {
3573 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3574 continue;
3575 }
3576
Jeff Sharkey85f5f812013-10-07 10:16:12 -07003577 if (parser.getName().equals("intent-filter")) {
3578 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08003579 if (!parseIntent(res, parser, attrs, true, false, intent, outError)) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07003580 return false;
3581 }
3582 outInfo.intents.add(intent);
3583
3584 } else if (parser.getName().equals("meta-data")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003585 if ((outInfo.metaData=parseMetaData(res, parser, attrs,
3586 outInfo.metaData, outError)) == null) {
3587 return false;
3588 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003590 } else if (parser.getName().equals("grant-uri-permission")) {
3591 TypedArray sa = res.obtainAttributes(attrs,
3592 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
3593
3594 PatternMatcher pa = null;
3595
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003596 String str = sa.getNonConfigurationString(
3597 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003598 if (str != null) {
3599 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
3600 }
3601
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003602 str = sa.getNonConfigurationString(
3603 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003604 if (str != null) {
3605 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
3606 }
3607
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003608 str = sa.getNonConfigurationString(
3609 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003610 if (str != null) {
3611 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
3612 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003614 sa.recycle();
3615
3616 if (pa != null) {
3617 if (outInfo.info.uriPermissionPatterns == null) {
3618 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
3619 outInfo.info.uriPermissionPatterns[0] = pa;
3620 } else {
3621 final int N = outInfo.info.uriPermissionPatterns.length;
3622 PatternMatcher[] newp = new PatternMatcher[N+1];
3623 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
3624 newp[N] = pa;
3625 outInfo.info.uriPermissionPatterns = newp;
3626 }
3627 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003628 } else {
3629 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003630 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003631 + parser.getName() + " at " + mArchiveSourcePath + " "
3632 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003633 XmlUtils.skipCurrentTag(parser);
3634 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003635 } else {
3636 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
3637 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003638 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003639 }
3640 XmlUtils.skipCurrentTag(parser);
3641
3642 } else if (parser.getName().equals("path-permission")) {
3643 TypedArray sa = res.obtainAttributes(attrs,
3644 com.android.internal.R.styleable.AndroidManifestPathPermission);
3645
3646 PathPermission pa = null;
3647
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003648 String permission = sa.getNonConfigurationString(
3649 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
3650 String readPermission = sa.getNonConfigurationString(
3651 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003652 if (readPermission == null) {
3653 readPermission = permission;
3654 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003655 String writePermission = sa.getNonConfigurationString(
3656 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003657 if (writePermission == null) {
3658 writePermission = permission;
3659 }
3660
3661 boolean havePerm = false;
3662 if (readPermission != null) {
3663 readPermission = readPermission.intern();
3664 havePerm = true;
3665 }
3666 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00003667 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003668 havePerm = true;
3669 }
3670
3671 if (!havePerm) {
3672 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003673 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003674 + parser.getName() + " at " + mArchiveSourcePath + " "
3675 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003676 XmlUtils.skipCurrentTag(parser);
3677 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003678 } else {
3679 outError[0] = "No readPermission or writePermssion for <path-permission>";
3680 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003681 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003682 }
3683
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003684 String path = sa.getNonConfigurationString(
3685 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003686 if (path != null) {
3687 pa = new PathPermission(path,
3688 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
3689 }
3690
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003691 path = sa.getNonConfigurationString(
3692 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003693 if (path != null) {
3694 pa = new PathPermission(path,
3695 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
3696 }
3697
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003698 path = sa.getNonConfigurationString(
3699 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003700 if (path != null) {
3701 pa = new PathPermission(path,
3702 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
3703 }
3704
3705 sa.recycle();
3706
3707 if (pa != null) {
3708 if (outInfo.info.pathPermissions == null) {
3709 outInfo.info.pathPermissions = new PathPermission[1];
3710 outInfo.info.pathPermissions[0] = pa;
3711 } else {
3712 final int N = outInfo.info.pathPermissions.length;
3713 PathPermission[] newp = new PathPermission[N+1];
3714 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
3715 newp[N] = pa;
3716 outInfo.info.pathPermissions = newp;
3717 }
3718 } else {
3719 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003720 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003721 + parser.getName() + " at " + mArchiveSourcePath + " "
3722 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003723 XmlUtils.skipCurrentTag(parser);
3724 continue;
3725 }
3726 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
3727 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003728 }
3729 XmlUtils.skipCurrentTag(parser);
3730
3731 } else {
3732 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003733 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003734 + parser.getName() + " at " + mArchiveSourcePath + " "
3735 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003736 XmlUtils.skipCurrentTag(parser);
3737 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003738 } else {
3739 outError[0] = "Bad element under <provider>: " + parser.getName();
3740 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003741 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003742 }
3743 }
3744 return true;
3745 }
3746
3747 private Service parseService(Package owner, Resources res,
3748 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
3749 throws XmlPullParserException, IOException {
3750 TypedArray sa = res.obtainAttributes(attrs,
3751 com.android.internal.R.styleable.AndroidManifestService);
3752
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003753 if (mParseServiceArgs == null) {
3754 mParseServiceArgs = new ParseComponentArgs(owner, outError,
3755 com.android.internal.R.styleable.AndroidManifestService_name,
3756 com.android.internal.R.styleable.AndroidManifestService_label,
3757 com.android.internal.R.styleable.AndroidManifestService_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07003758 com.android.internal.R.styleable.AndroidManifestService_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08003759 com.android.internal.R.styleable.AndroidManifestService_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003760 mSeparateProcesses,
3761 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003762 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003763 com.android.internal.R.styleable.AndroidManifestService_enabled);
3764 mParseServiceArgs.tag = "<service>";
3765 }
3766
3767 mParseServiceArgs.sa = sa;
3768 mParseServiceArgs.flags = flags;
3769
3770 Service s = new Service(mParseServiceArgs, new ServiceInfo());
3771 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003772 sa.recycle();
3773 return null;
3774 }
3775
Dianne Hackbornb4163a62012-08-02 18:31:26 -07003776 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003777 com.android.internal.R.styleable.AndroidManifestService_exported);
3778 if (setExported) {
3779 s.info.exported = sa.getBoolean(
3780 com.android.internal.R.styleable.AndroidManifestService_exported, false);
3781 }
3782
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003783 String str = sa.getNonConfigurationString(
3784 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003785 if (str == null) {
3786 s.info.permission = owner.applicationInfo.permission;
3787 } else {
3788 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
3789 }
3790
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003791 s.info.flags = 0;
3792 if (sa.getBoolean(
3793 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
3794 false)) {
3795 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
3796 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08003797 if (sa.getBoolean(
3798 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
3799 false)) {
3800 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
3801 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07003802 if (sa.getBoolean(
3803 com.android.internal.R.styleable.AndroidManifestService_singleUser,
3804 false)) {
3805 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003806 if (s.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackbornb4163a62012-08-02 18:31:26 -07003807 Slog.w(TAG, "Service exported request ignored due to singleUser: "
3808 + s.className + " at " + mArchiveSourcePath + " "
3809 + parser.getPositionDescription());
3810 s.info.exported = false;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003811 setExported = true;
Dianne Hackbornb4163a62012-08-02 18:31:26 -07003812 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07003813 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003815 sa.recycle();
3816
Alex Klyubinb9f8a522015-02-03 11:12:59 -08003817 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
3818 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07003819 // A heavy-weight application can not have services in its main process
3820 // We can do direct compare because we intern all strings.
3821 if (s.info.processName == owner.packageName) {
3822 outError[0] = "Heavy-weight applications can not have services in main process";
3823 return null;
3824 }
3825 }
3826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003827 int outerDepth = parser.getDepth();
3828 int type;
3829 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3830 && (type != XmlPullParser.END_TAG
3831 || parser.getDepth() > outerDepth)) {
3832 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3833 continue;
3834 }
3835
3836 if (parser.getName().equals("intent-filter")) {
3837 ServiceIntentInfo intent = new ServiceIntentInfo(s);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08003838 if (!parseIntent(res, parser, attrs, true, false, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003839 return null;
3840 }
3841
3842 s.intents.add(intent);
3843 } else if (parser.getName().equals("meta-data")) {
3844 if ((s.metaData=parseMetaData(res, parser, attrs, s.metaData,
3845 outError)) == null) {
3846 return null;
3847 }
3848 } else {
3849 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003850 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003851 + parser.getName() + " at " + mArchiveSourcePath + " "
3852 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003853 XmlUtils.skipCurrentTag(parser);
3854 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003855 } else {
3856 outError[0] = "Bad element under <service>: " + parser.getName();
3857 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003858 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003859 }
3860 }
3861
3862 if (!setExported) {
3863 s.info.exported = s.intents.size() > 0;
3864 }
3865
3866 return s;
3867 }
3868
3869 private boolean parseAllMetaData(Resources res,
3870 XmlPullParser parser, AttributeSet attrs, String tag,
3871 Component outInfo, String[] outError)
3872 throws XmlPullParserException, IOException {
3873 int outerDepth = parser.getDepth();
3874 int type;
3875 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3876 && (type != XmlPullParser.END_TAG
3877 || parser.getDepth() > outerDepth)) {
3878 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3879 continue;
3880 }
3881
3882 if (parser.getName().equals("meta-data")) {
3883 if ((outInfo.metaData=parseMetaData(res, parser, attrs,
3884 outInfo.metaData, outError)) == null) {
3885 return false;
3886 }
3887 } else {
3888 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003889 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003890 + parser.getName() + " at " + mArchiveSourcePath + " "
3891 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003892 XmlUtils.skipCurrentTag(parser);
3893 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003894 } else {
3895 outError[0] = "Bad element under " + tag + ": " + parser.getName();
3896 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003897 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003898 }
3899 }
3900 return true;
3901 }
3902
3903 private Bundle parseMetaData(Resources res,
3904 XmlPullParser parser, AttributeSet attrs,
3905 Bundle data, String[] outError)
3906 throws XmlPullParserException, IOException {
3907
3908 TypedArray sa = res.obtainAttributes(attrs,
3909 com.android.internal.R.styleable.AndroidManifestMetaData);
3910
3911 if (data == null) {
3912 data = new Bundle();
3913 }
3914
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003915 String name = sa.getNonConfigurationString(
3916 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003917 if (name == null) {
3918 outError[0] = "<meta-data> requires an android:name attribute";
3919 sa.recycle();
3920 return null;
3921 }
3922
Dianne Hackborn854060af2009-07-09 18:14:31 -07003923 name = name.intern();
3924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003925 TypedValue v = sa.peekValue(
3926 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
3927 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003928 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003929 data.putInt(name, v.resourceId);
3930 } else {
3931 v = sa.peekValue(
3932 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07003933 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003934 if (v != null) {
3935 if (v.type == TypedValue.TYPE_STRING) {
3936 CharSequence cs = v.coerceToString();
Dianne Hackborn854060af2009-07-09 18:14:31 -07003937 data.putString(name, cs != null ? cs.toString().intern() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003938 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
3939 data.putBoolean(name, v.data != 0);
3940 } else if (v.type >= TypedValue.TYPE_FIRST_INT
3941 && v.type <= TypedValue.TYPE_LAST_INT) {
3942 data.putInt(name, v.data);
3943 } else if (v.type == TypedValue.TYPE_FLOAT) {
3944 data.putFloat(name, v.getFloat());
3945 } else {
3946 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003947 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003948 + parser.getName() + " at " + mArchiveSourcePath + " "
3949 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003950 } else {
3951 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
3952 data = null;
3953 }
3954 }
3955 } else {
3956 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
3957 data = null;
3958 }
3959 }
3960
3961 sa.recycle();
3962
3963 XmlUtils.skipCurrentTag(parser);
3964
3965 return data;
3966 }
3967
Kenny Root05ca4c92011-09-15 10:36:25 -07003968 private static VerifierInfo parseVerifier(Resources res, XmlPullParser parser,
Jeff Sharkey275e0852014-06-17 18:18:49 -07003969 AttributeSet attrs, int flags) {
Kenny Root05ca4c92011-09-15 10:36:25 -07003970 final TypedArray sa = res.obtainAttributes(attrs,
3971 com.android.internal.R.styleable.AndroidManifestPackageVerifier);
3972
3973 final String packageName = sa.getNonResourceString(
3974 com.android.internal.R.styleable.AndroidManifestPackageVerifier_name);
3975
3976 final String encodedPublicKey = sa.getNonResourceString(
3977 com.android.internal.R.styleable.AndroidManifestPackageVerifier_publicKey);
3978
3979 sa.recycle();
3980
3981 if (packageName == null || packageName.length() == 0) {
3982 Slog.i(TAG, "verifier package name was null; skipping");
3983 return null;
Kenny Root05ca4c92011-09-15 10:36:25 -07003984 }
3985
Christopher Tate30147332014-04-15 12:57:47 -07003986 final PublicKey publicKey = parsePublicKey(encodedPublicKey);
3987 if (publicKey == null) {
3988 Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
3989 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -08003990 }
3991
Christopher Tate30147332014-04-15 12:57:47 -07003992 return new VerifierInfo(packageName, publicKey);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003993 }
3994
Christopher Tate30147332014-04-15 12:57:47 -07003995 public static final PublicKey parsePublicKey(final String encodedPublicKey) {
3996 if (encodedPublicKey == null) {
3997 Slog.i(TAG, "Could not parse null public key");
3998 return null;
3999 }
4000
Kenny Root05ca4c92011-09-15 10:36:25 -07004001 EncodedKeySpec keySpec;
4002 try {
4003 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
4004 keySpec = new X509EncodedKeySpec(encoded);
4005 } catch (IllegalArgumentException e) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08004006 Slog.i(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07004007 return null;
4008 }
4009
4010 /* First try the key as an RSA key. */
4011 try {
4012 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08004013 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07004014 } catch (NoSuchAlgorithmException e) {
4015 Log.wtf(TAG, "Could not parse public key because RSA isn't included in build");
4016 return null;
4017 } catch (InvalidKeySpecException e) {
4018 // Not a RSA public key.
4019 }
4020
4021 /* Now try it as a DSA key. */
4022 try {
4023 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08004024 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07004025 } catch (NoSuchAlgorithmException e) {
4026 Log.wtf(TAG, "Could not parse public key because DSA isn't included in build");
4027 return null;
4028 } catch (InvalidKeySpecException e) {
4029 // Not a DSA public key.
4030 }
4031
4032 return null;
4033 }
4034
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004035 private static final String ANDROID_RESOURCES
4036 = "http://schemas.android.com/apk/res/android";
4037
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004038 private boolean parseIntent(Resources res, XmlPullParser parser, AttributeSet attrs,
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08004039 boolean allowGlobs, boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004040 throws XmlPullParserException, IOException {
4041
4042 TypedArray sa = res.obtainAttributes(attrs,
4043 com.android.internal.R.styleable.AndroidManifestIntentFilter);
4044
4045 int priority = sa.getInt(
4046 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004047 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08004048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004049 TypedValue v = sa.peekValue(
4050 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
4051 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4052 outInfo.nonLocalizedLabel = v.coerceToString();
4053 }
4054
4055 outInfo.icon = sa.getResourceId(
4056 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
Adam Powell81cd2e92010-04-21 16:35:18 -07004057
4058 outInfo.logo = sa.getResourceId(
4059 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004060
Jose Limaf78e3122014-03-06 12:13:15 -08004061 outInfo.banner = sa.getResourceId(
4062 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
4063
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08004064 if (allowAutoVerify) {
4065 outInfo.setAutoVerify(sa.getBoolean(
4066 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
4067 false));
4068 }
4069
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004070 sa.recycle();
4071
4072 int outerDepth = parser.getDepth();
4073 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07004074 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
4075 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
4076 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004077 continue;
4078 }
4079
4080 String nodeName = parser.getName();
4081 if (nodeName.equals("action")) {
4082 String value = attrs.getAttributeValue(
4083 ANDROID_RESOURCES, "name");
4084 if (value == null || value == "") {
4085 outError[0] = "No value supplied for <android:name>";
4086 return false;
4087 }
4088 XmlUtils.skipCurrentTag(parser);
4089
4090 outInfo.addAction(value);
4091 } else if (nodeName.equals("category")) {
4092 String value = attrs.getAttributeValue(
4093 ANDROID_RESOURCES, "name");
4094 if (value == null || value == "") {
4095 outError[0] = "No value supplied for <android:name>";
4096 return false;
4097 }
4098 XmlUtils.skipCurrentTag(parser);
4099
4100 outInfo.addCategory(value);
4101
4102 } else if (nodeName.equals("data")) {
4103 sa = res.obtainAttributes(attrs,
4104 com.android.internal.R.styleable.AndroidManifestData);
4105
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004106 String str = sa.getNonConfigurationString(
4107 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004108 if (str != null) {
4109 try {
4110 outInfo.addDataType(str);
4111 } catch (IntentFilter.MalformedMimeTypeException e) {
4112 outError[0] = e.toString();
4113 sa.recycle();
4114 return false;
4115 }
4116 }
4117
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004118 str = sa.getNonConfigurationString(
4119 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004120 if (str != null) {
4121 outInfo.addDataScheme(str);
4122 }
4123
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07004124 str = sa.getNonConfigurationString(
4125 com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
4126 if (str != null) {
4127 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
4128 }
4129
4130 str = sa.getNonConfigurationString(
4131 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
4132 if (str != null) {
4133 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
4134 }
4135
4136 str = sa.getNonConfigurationString(
4137 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
4138 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004139 if (!allowGlobs) {
4140 outError[0] = "sspPattern not allowed here; ssp must be literal";
4141 return false;
4142 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07004143 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4144 }
4145
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004146 String host = sa.getNonConfigurationString(
4147 com.android.internal.R.styleable.AndroidManifestData_host, 0);
4148 String port = sa.getNonConfigurationString(
4149 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004150 if (host != null) {
4151 outInfo.addDataAuthority(host, port);
4152 }
4153
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004154 str = sa.getNonConfigurationString(
4155 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004156 if (str != null) {
4157 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
4158 }
4159
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004160 str = sa.getNonConfigurationString(
4161 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004162 if (str != null) {
4163 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
4164 }
4165
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004166 str = sa.getNonConfigurationString(
4167 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004168 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004169 if (!allowGlobs) {
4170 outError[0] = "pathPattern not allowed here; path must be literal";
4171 return false;
4172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4174 }
4175
4176 sa.recycle();
4177 XmlUtils.skipCurrentTag(parser);
4178 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004179 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004180 + parser.getName() + " at " + mArchiveSourcePath + " "
4181 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004182 XmlUtils.skipCurrentTag(parser);
4183 } else {
4184 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
4185 return false;
4186 }
4187 }
4188
4189 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07004190
4191 if (DEBUG_PARSER) {
4192 final StringBuilder cats = new StringBuilder("Intent d=");
4193 cats.append(outInfo.hasDefault);
4194 cats.append(", cat=");
4195
4196 final Iterator<String> it = outInfo.categoriesIterator();
4197 if (it != null) {
4198 while (it.hasNext()) {
4199 cats.append(' ');
4200 cats.append(it.next());
4201 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004202 }
Kenny Rootd2d29252011-08-08 11:27:57 -07004203 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004204 }
4205
4206 return true;
4207 }
4208
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004209 /**
4210 * Representation of a full package parsed from APK files on disk. A package
4211 * consists of a single base APK, and zero or more split APKs.
4212 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004213 public final static class Package {
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07004214
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004215 public String packageName;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004216
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004217 /** Names of any split APKs, ordered by parsed splitName */
4218 public String[] splitNames;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004219
4220 // TODO: work towards making these paths invariant
Jeff Sharkey275e0852014-06-17 18:18:49 -07004221
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07004222 public String volumeUuid;
4223
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004224 /**
4225 * Path where this package was found on disk. For monolithic packages
4226 * this is path to single base APK file; for cluster packages this is
4227 * path to the cluster directory.
4228 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004229 public String codePath;
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004230
4231 /** Path of base APK */
4232 public String baseCodePath;
4233 /** Paths of any split APKs, ordered by parsed splitName */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004234 public String[] splitCodePaths;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004235
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004236 /** Revision code of base APK */
4237 public int baseRevisionCode;
4238 /** Revision codes of any split APKs, ordered by parsed splitName */
4239 public int[] splitRevisionCodes;
4240
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004241 /** Flags of any split APKs; ordered by parsed splitName */
4242 public int[] splitFlags;
4243
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004244 /**
4245 * Private flags of any split APKs; ordered by parsed splitName.
4246 *
4247 * {@hide}
4248 */
4249 public int[] splitPrivateFlags;
4250
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004251 public boolean baseHardwareAccelerated;
4252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004253 // For now we only support one application per package.
4254 public final ApplicationInfo applicationInfo = new ApplicationInfo();
4255
4256 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
4257 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
4258 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
4259 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
4260 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
4261 public final ArrayList<Service> services = new ArrayList<Service>(0);
4262 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
4263
4264 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
4265
Dianne Hackborn854060af2009-07-09 18:14:31 -07004266 public ArrayList<String> protectedBroadcasts;
Dianne Hackbornc895be72013-03-11 17:48:43 -07004267
4268 public ArrayList<String> libraryNames = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07004269 public ArrayList<String> usesLibraries = null;
4270 public ArrayList<String> usesOptionalLibraries = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004271 public String[] usesLibraryFiles = null;
4272
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004273 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
4274
Dianne Hackbornc1552392010-03-03 16:19:01 -08004275 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004276 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08004277 public ArrayList<String> mAdoptPermissions = null;
4278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004279 // We store the application meta-data independently to avoid multiple unwanted references
4280 public Bundle mAppMetaData = null;
4281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004282 // The version code declared for this package.
4283 public int mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004285 // The version name declared for this package.
4286 public String mVersionName;
4287
4288 // The shared user id that this package wants to use.
4289 public String mSharedUserId;
4290
4291 // The shared user label that this package wants to use.
4292 public int mSharedUserLabel;
4293
4294 // Signatures that were read from the package.
Jeff Sharkey275e0852014-06-17 18:18:49 -07004295 public Signature[] mSignatures;
4296 public Certificate[][] mCertificates;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004297
4298 // For use by package manager service for quick lookup of
4299 // preferred up order.
4300 public int mPreferredOrder = 0;
4301
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07004302 // For use by package manager to keep track of where it needs to do dexopt.
Narayan Kamath20531682014-07-14 13:18:43 +01004303 public final ArraySet<String> mDexOptPerformed = new ArraySet<>(4);
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07004304
4305 // For use by package manager to keep track of when a package was last used.
4306 public long mLastPackageUsageTimeInMills;
4307
Amith Yamasani13593602012-03-22 16:16:17 -07004308 // // User set enabled state.
4309 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
4310 //
4311 // // Whether the package has been stopped.
4312 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004314 // Additional data supplied by callers.
4315 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07004316
4317 // Whether an operation is currently pending on this package
4318 public boolean mOperationPending;
4319
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004320 // Applications hardware preferences
4321 public ArrayList<ConfigurationInfo> configPreferences = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004322
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004323 // Applications requested features
Dianne Hackborn49237342009-08-27 20:08:01 -07004324 public ArrayList<FeatureInfo> reqFeatures = null;
4325
Adam Lesinskid3edfde2014-08-08 17:32:44 -07004326 // Applications requested feature groups
4327 public ArrayList<FeatureGroupInfo> featureGroups = null;
4328
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08004329 public int installLocation;
4330
Jeff Hao272bf3a2014-10-08 13:34:43 -07004331 public boolean coreApp;
4332
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08004333 /* An app that's required for all users and cannot be uninstalled for a user */
4334 public boolean mRequiredForAllUsers;
4335
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07004336 /* The restricted account authenticator type that is used by this application */
4337 public String mRestrictedAccountType;
4338
Amith Yamasaniccbe3892013-04-12 17:52:42 -07004339 /* The required account type without which this application will not function */
4340 public String mRequiredAccountType;
4341
Kenny Rootbcc954d2011-08-08 16:19:08 -07004342 /**
4343 * Digest suitable for comparing whether this package's manifest is the
4344 * same as another.
4345 */
4346 public ManifestDigest manifestDigest;
4347
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01004348 public String mOverlayTarget;
4349 public int mOverlayPriority;
4350 public boolean mTrustedOverlay;
4351
Geremy Condraf1bcca82013-01-07 22:35:24 -08004352 /**
dcashman989eb3712014-06-17 12:56:12 -07004353 * Data used to feed the KeySetManagerService
Geremy Condraf1bcca82013-01-07 22:35:24 -08004354 */
dcashman989eb3712014-06-17 12:56:12 -07004355 public ArraySet<PublicKey> mSigningKeys;
4356 public ArraySet<String> mUpgradeKeySets;
4357 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -08004358
Narayan Kamath4903f642014-08-11 13:33:45 +01004359 /**
4360 * The install time abi override for this package, if any.
4361 *
4362 * TODO: This seems like a horrible place to put the abiOverride because
4363 * this isn't something the packageParser parsers. However, this fits in with
4364 * the rest of the PackageManager where package scanning randomly pushes
4365 * and prods fields out of {@code this.applicationInfo}.
4366 */
4367 public String cpuAbiOverride;
4368
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004369 public Package(String packageName) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07004370 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07004371 applicationInfo.packageName = packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004372 applicationInfo.uid = -1;
4373 }
4374
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004375 public List<String> getAllCodePaths() {
Jeff Sharkey275e0852014-06-17 18:18:49 -07004376 ArrayList<String> paths = new ArrayList<>();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004377 paths.add(baseCodePath);
Jeff Sharkey275e0852014-06-17 18:18:49 -07004378 if (!ArrayUtils.isEmpty(splitCodePaths)) {
4379 Collections.addAll(paths, splitCodePaths);
4380 }
4381 return paths;
4382 }
4383
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004384 /**
4385 * Filtered set of {@link #getAllCodePaths()} that excludes
4386 * resource-only APKs.
4387 */
4388 public List<String> getAllCodePathsExcludingResourceOnly() {
4389 ArrayList<String> paths = new ArrayList<>();
4390 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
4391 paths.add(baseCodePath);
4392 }
4393 if (!ArrayUtils.isEmpty(splitCodePaths)) {
4394 for (int i = 0; i < splitCodePaths.length; i++) {
4395 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
4396 paths.add(splitCodePaths[i]);
4397 }
4398 }
4399 }
4400 return paths;
4401 }
4402
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004403 public void setPackageName(String newName) {
4404 packageName = newName;
4405 applicationInfo.packageName = newName;
4406 for (int i=permissions.size()-1; i>=0; i--) {
4407 permissions.get(i).setPackageName(newName);
4408 }
4409 for (int i=permissionGroups.size()-1; i>=0; i--) {
4410 permissionGroups.get(i).setPackageName(newName);
4411 }
4412 for (int i=activities.size()-1; i>=0; i--) {
4413 activities.get(i).setPackageName(newName);
4414 }
4415 for (int i=receivers.size()-1; i>=0; i--) {
4416 receivers.get(i).setPackageName(newName);
4417 }
4418 for (int i=providers.size()-1; i>=0; i--) {
4419 providers.get(i).setPackageName(newName);
4420 }
4421 for (int i=services.size()-1; i>=0; i--) {
4422 services.get(i).setPackageName(newName);
4423 }
4424 for (int i=instrumentation.size()-1; i>=0; i--) {
4425 instrumentation.get(i).setPackageName(newName);
4426 }
4427 }
Dianne Hackborn65696252012-03-05 18:49:21 -08004428
4429 public boolean hasComponentClassName(String name) {
4430 for (int i=activities.size()-1; i>=0; i--) {
4431 if (name.equals(activities.get(i).className)) {
4432 return true;
4433 }
4434 }
4435 for (int i=receivers.size()-1; i>=0; i--) {
4436 if (name.equals(receivers.get(i).className)) {
4437 return true;
4438 }
4439 }
4440 for (int i=providers.size()-1; i>=0; i--) {
4441 if (name.equals(providers.get(i).className)) {
4442 return true;
4443 }
4444 }
4445 for (int i=services.size()-1; i>=0; i--) {
4446 if (name.equals(services.get(i).className)) {
4447 return true;
4448 }
4449 }
4450 for (int i=instrumentation.size()-1; i>=0; i--) {
4451 if (name.equals(instrumentation.get(i).className)) {
4452 return true;
4453 }
4454 }
4455 return false;
4456 }
4457
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08004458 /**
4459 * @hide
4460 */
4461 public boolean isForwardLocked() {
4462 return applicationInfo.isForwardLocked();
4463 }
4464
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08004465 /**
4466 * @hide
4467 */
4468 public boolean isSystemApp() {
4469 return applicationInfo.isSystemApp();
4470 }
4471
4472 /**
4473 * @hide
4474 */
4475 public boolean isUpdatedSystemApp() {
4476 return applicationInfo.isUpdatedSystemApp();
4477 }
4478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004479 public String toString() {
4480 return "Package{"
4481 + Integer.toHexString(System.identityHashCode(this))
4482 + " " + packageName + "}";
4483 }
4484 }
4485
4486 public static class Component<II extends IntentInfo> {
4487 public final Package owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004488 public final ArrayList<II> intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004489 public final String className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004490 public Bundle metaData;
4491
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004492 ComponentName componentName;
4493 String componentShortName;
4494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004495 public Component(Package _owner) {
4496 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004497 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004498 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004499 }
4500
4501 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
4502 owner = args.owner;
4503 intents = new ArrayList<II>(0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004504 String name = args.sa.getNonConfigurationString(args.nameRes, 0);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004505 if (name == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004506 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004507 args.outError[0] = args.tag + " does not specify android:name";
4508 return;
4509 }
4510
4511 outInfo.name
4512 = buildClassName(owner.applicationInfo.packageName, name, args.outError);
4513 if (outInfo.name == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004514 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004515 args.outError[0] = args.tag + " does not have valid android:name";
4516 return;
4517 }
4518
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004519 className = outInfo.name;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004520
4521 int iconVal = args.sa.getResourceId(args.iconRes, 0);
4522 if (iconVal != 0) {
4523 outInfo.icon = iconVal;
4524 outInfo.nonLocalizedLabel = null;
4525 }
Adam Powell81cd2e92010-04-21 16:35:18 -07004526
4527 int logoVal = args.sa.getResourceId(args.logoRes, 0);
4528 if (logoVal != 0) {
4529 outInfo.logo = logoVal;
4530 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004531
Jose Limaf78e3122014-03-06 12:13:15 -08004532 int bannerVal = args.sa.getResourceId(args.bannerRes, 0);
4533 if (bannerVal != 0) {
4534 outInfo.banner = bannerVal;
4535 }
4536
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004537 TypedValue v = args.sa.peekValue(args.labelRes);
4538 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4539 outInfo.nonLocalizedLabel = v.coerceToString();
4540 }
4541
4542 outInfo.packageName = owner.packageName;
4543 }
4544
4545 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
4546 this(args, (PackageItemInfo)outInfo);
4547 if (args.outError[0] != null) {
4548 return;
4549 }
4550
4551 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07004552 CharSequence pname;
4553 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004554 pname = args.sa.getNonConfigurationString(args.processRes,
4555 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07004556 } else {
4557 // Some older apps have been seen to use a resource reference
4558 // here that on older builds was ignored (with a warning). We
4559 // need to continue to do this for them so they don't break.
4560 pname = args.sa.getNonResourceString(args.processRes);
4561 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004562 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07004563 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004564 args.flags, args.sepProcesses, args.outError);
4565 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004566
4567 if (args.descriptionRes != 0) {
4568 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
4569 }
4570
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004571 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004572 }
4573
4574 public Component(Component<II> clone) {
4575 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004576 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004577 className = clone.className;
4578 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004579 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004580 }
4581
4582 public ComponentName getComponentName() {
4583 if (componentName != null) {
4584 return componentName;
4585 }
4586 if (className != null) {
4587 componentName = new ComponentName(owner.applicationInfo.packageName,
4588 className);
4589 }
4590 return componentName;
4591 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07004592
4593 public void appendComponentShortName(StringBuilder sb) {
4594 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004595 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07004596
4597 public void printComponentShortName(PrintWriter pw) {
4598 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
4599 }
4600
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004601 public void setPackageName(String packageName) {
4602 componentName = null;
4603 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004604 }
4605 }
4606
4607 public final static class Permission extends Component<IntentInfo> {
4608 public final PermissionInfo info;
4609 public boolean tree;
4610 public PermissionGroup group;
4611
4612 public Permission(Package _owner) {
4613 super(_owner);
4614 info = new PermissionInfo();
4615 }
4616
4617 public Permission(Package _owner, PermissionInfo _info) {
4618 super(_owner);
4619 info = _info;
4620 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004621
4622 public void setPackageName(String packageName) {
4623 super.setPackageName(packageName);
4624 info.packageName = packageName;
4625 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004626
4627 public String toString() {
4628 return "Permission{"
4629 + Integer.toHexString(System.identityHashCode(this))
4630 + " " + info.name + "}";
4631 }
4632 }
4633
4634 public final static class PermissionGroup extends Component<IntentInfo> {
4635 public final PermissionGroupInfo info;
4636
4637 public PermissionGroup(Package _owner) {
4638 super(_owner);
4639 info = new PermissionGroupInfo();
4640 }
4641
4642 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
4643 super(_owner);
4644 info = _info;
4645 }
4646
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004647 public void setPackageName(String packageName) {
4648 super.setPackageName(packageName);
4649 info.packageName = packageName;
4650 }
4651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004652 public String toString() {
4653 return "PermissionGroup{"
4654 + Integer.toHexString(System.identityHashCode(this))
4655 + " " + info.name + "}";
4656 }
4657 }
4658
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004659 private static boolean copyNeeded(int flags, Package p,
4660 PackageUserState state, Bundle metaData, int userId) {
Amith Yamasani1742cfb2015-04-14 15:41:20 -07004661 if (userId != UserHandle.USER_OWNER) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004662 // We always need to copy for other users, since we need
4663 // to fix up the uid.
4664 return true;
4665 }
4666 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
4667 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07004668 if (p.applicationInfo.enabled != enabled) {
4669 return true;
4670 }
4671 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004672 if (!state.installed || state.hidden) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004673 return true;
4674 }
4675 if (state.stopped) {
4676 return true;
4677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004678 if ((flags & PackageManager.GET_META_DATA) != 0
4679 && (metaData != null || p.mAppMetaData != null)) {
4680 return true;
4681 }
4682 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
4683 && p.usesLibraryFiles != null) {
4684 return true;
4685 }
4686 return false;
4687 }
4688
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004689 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
4690 PackageUserState state) {
4691 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07004692 }
4693
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08004694 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
4695 PackageUserState state) {
4696 // CompatibilityMode is global state.
4697 if (!sCompatibilityModeEnabled) {
4698 ai.disableCompatibilityMode();
4699 }
4700 if (state.installed) {
4701 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
4702 } else {
4703 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
4704 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004705 if (state.hidden) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004706 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07004707 } else {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004708 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07004709 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08004710 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
4711 ai.enabled = true;
4712 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
4713 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
4714 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
4715 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
4716 ai.enabled = false;
4717 }
4718 ai.enabledSetting = state.enabled;
4719 }
4720
Amith Yamasani13593602012-03-22 16:16:17 -07004721 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004722 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004723 if (p == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004724 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004725 return null;
4726 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08004727 if (!copyNeeded(flags, p, state, null, userId)
4728 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
4729 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
4730 // In this case it is safe to directly modify the internal ApplicationInfo state:
4731 // - CompatibilityMode is global state, so will be the same for every call.
4732 // - We only come in to here if the app should reported as installed; this is the
4733 // default state, and we will do a copy otherwise.
4734 // - The enable state will always be reported the same for the application across
4735 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
4736 // be doing a copy.
4737 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004738 return p.applicationInfo;
4739 }
4740
4741 // Make shallow copy so we can store the metadata/libraries safely
4742 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Amith Yamasani1742cfb2015-04-14 15:41:20 -07004743 ai.uid = UserHandle.getUid(userId, ai.uid);
4744 ai.dataDir = PackageManager.getDataDirForUser(ai.volumeUuid, ai.packageName, userId)
4745 .getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004746 if ((flags & PackageManager.GET_META_DATA) != 0) {
4747 ai.metaData = p.mAppMetaData;
4748 }
4749 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
4750 ai.sharedLibraryFiles = p.usesLibraryFiles;
4751 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004752 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07004753 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004754 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07004755 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004756 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08004757 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004758 return ai;
4759 }
4760
Dianne Hackbornace27912014-09-18 18:38:30 -07004761 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
4762 PackageUserState state, int userId) {
4763 if (ai == null) return null;
4764 if (!checkUseInstalledOrHidden(flags, state)) {
4765 return null;
4766 }
4767 // This is only used to return the ResolverActivity; we will just always
4768 // make a copy.
4769 ai = new ApplicationInfo(ai);
Amith Yamasani1742cfb2015-04-14 15:41:20 -07004770 ai.uid = UserHandle.getUid(userId, ai.uid);
4771 ai.dataDir = PackageManager.getDataDirForUser(ai.volumeUuid, ai.packageName, userId)
4772 .getAbsolutePath();
Dianne Hackbornace27912014-09-18 18:38:30 -07004773 if (state.stopped) {
4774 ai.flags |= ApplicationInfo.FLAG_STOPPED;
4775 } else {
4776 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
4777 }
4778 updateApplicationInfo(ai, flags, state);
4779 return ai;
4780 }
4781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004782 public static final PermissionInfo generatePermissionInfo(
4783 Permission p, int flags) {
4784 if (p == null) return null;
4785 if ((flags&PackageManager.GET_META_DATA) == 0) {
4786 return p.info;
4787 }
4788 PermissionInfo pi = new PermissionInfo(p.info);
4789 pi.metaData = p.metaData;
4790 return pi;
4791 }
4792
4793 public static final PermissionGroupInfo generatePermissionGroupInfo(
4794 PermissionGroup pg, int flags) {
4795 if (pg == null) return null;
4796 if ((flags&PackageManager.GET_META_DATA) == 0) {
4797 return pg.info;
4798 }
4799 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
4800 pgi.metaData = pg.metaData;
4801 return pgi;
4802 }
4803
4804 public final static class Activity extends Component<ActivityIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004805 public final ActivityInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004806
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004807 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
4808 super(args, _info);
4809 info = _info;
4810 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004811 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004812
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004813 public void setPackageName(String packageName) {
4814 super.setPackageName(packageName);
4815 info.packageName = packageName;
4816 }
4817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004818 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07004819 StringBuilder sb = new StringBuilder(128);
4820 sb.append("Activity{");
4821 sb.append(Integer.toHexString(System.identityHashCode(this)));
4822 sb.append(' ');
4823 appendComponentShortName(sb);
4824 sb.append('}');
4825 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004826 }
4827 }
4828
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004829 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
4830 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004831 if (a == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004832 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004833 return null;
4834 }
4835 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004836 return a.info;
4837 }
4838 // Make shallow copies so we can store the metadata safely
4839 ActivityInfo ai = new ActivityInfo(a.info);
4840 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004841 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004842 return ai;
4843 }
4844
Dianne Hackbornace27912014-09-18 18:38:30 -07004845 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
4846 PackageUserState state, int userId) {
4847 if (ai == null) return null;
4848 if (!checkUseInstalledOrHidden(flags, state)) {
4849 return null;
4850 }
4851 // This is only used to return the ResolverActivity; we will just always
4852 // make a copy.
4853 ai = new ActivityInfo(ai);
4854 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
4855 return ai;
4856 }
4857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004858 public final static class Service extends Component<ServiceIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004859 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004860
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004861 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
4862 super(args, _info);
4863 info = _info;
4864 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004865 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004866
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004867 public void setPackageName(String packageName) {
4868 super.setPackageName(packageName);
4869 info.packageName = packageName;
4870 }
4871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004872 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07004873 StringBuilder sb = new StringBuilder(128);
4874 sb.append("Service{");
4875 sb.append(Integer.toHexString(System.identityHashCode(this)));
4876 sb.append(' ');
4877 appendComponentShortName(sb);
4878 sb.append('}');
4879 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004880 }
4881 }
4882
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004883 public static final ServiceInfo generateServiceInfo(Service s, int flags,
4884 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004885 if (s == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004886 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004887 return null;
4888 }
4889 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004890 return s.info;
4891 }
4892 // Make shallow copies so we can store the metadata safely
4893 ServiceInfo si = new ServiceInfo(s.info);
4894 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004895 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004896 return si;
4897 }
4898
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004899 public final static class Provider extends Component<ProviderIntentInfo> {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004900 public final ProviderInfo info;
4901 public boolean syncable;
4902
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004903 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
4904 super(args, _info);
4905 info = _info;
4906 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004907 syncable = false;
4908 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004910 public Provider(Provider existingProvider) {
4911 super(existingProvider);
4912 this.info = existingProvider.info;
4913 this.syncable = existingProvider.syncable;
4914 }
4915
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004916 public void setPackageName(String packageName) {
4917 super.setPackageName(packageName);
4918 info.packageName = packageName;
4919 }
4920
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004921 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07004922 StringBuilder sb = new StringBuilder(128);
4923 sb.append("Provider{");
4924 sb.append(Integer.toHexString(System.identityHashCode(this)));
4925 sb.append(' ');
4926 appendComponentShortName(sb);
4927 sb.append('}');
4928 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004929 }
4930 }
4931
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004932 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
4933 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004934 if (p == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004935 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004936 return null;
4937 }
4938 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004940 || p.info.uriPermissionPatterns == null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004941 return p.info;
4942 }
4943 // Make shallow copies so we can store the metadata safely
4944 ProviderInfo pi = new ProviderInfo(p.info);
4945 pi.metaData = p.metaData;
4946 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
4947 pi.uriPermissionPatterns = null;
4948 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004949 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004950 return pi;
4951 }
4952
4953 public final static class Instrumentation extends Component {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004954 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004955
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004956 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
4957 super(args, _info);
4958 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004959 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004960
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004961 public void setPackageName(String packageName) {
4962 super.setPackageName(packageName);
4963 info.packageName = packageName;
4964 }
4965
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004966 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07004967 StringBuilder sb = new StringBuilder(128);
4968 sb.append("Instrumentation{");
4969 sb.append(Integer.toHexString(System.identityHashCode(this)));
4970 sb.append(' ');
4971 appendComponentShortName(sb);
4972 sb.append('}');
4973 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004974 }
4975 }
4976
4977 public static final InstrumentationInfo generateInstrumentationInfo(
4978 Instrumentation i, int flags) {
4979 if (i == null) return null;
4980 if ((flags&PackageManager.GET_META_DATA) == 0) {
4981 return i.info;
4982 }
4983 InstrumentationInfo ii = new InstrumentationInfo(i.info);
4984 ii.metaData = i.metaData;
4985 return ii;
4986 }
4987
4988 public static class IntentInfo extends IntentFilter {
4989 public boolean hasDefault;
4990 public int labelRes;
4991 public CharSequence nonLocalizedLabel;
4992 public int icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07004993 public int logo;
Jose Limaf78e3122014-03-06 12:13:15 -08004994 public int banner;
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004995 public int preferred;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004996 }
4997
4998 public final static class ActivityIntentInfo extends IntentInfo {
4999 public final Activity activity;
5000
5001 public ActivityIntentInfo(Activity _activity) {
5002 activity = _activity;
5003 }
5004
5005 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005006 StringBuilder sb = new StringBuilder(128);
5007 sb.append("ActivityIntentInfo{");
5008 sb.append(Integer.toHexString(System.identityHashCode(this)));
5009 sb.append(' ');
5010 activity.appendComponentShortName(sb);
5011 sb.append('}');
5012 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005013 }
5014 }
5015
5016 public final static class ServiceIntentInfo extends IntentInfo {
5017 public final Service service;
5018
5019 public ServiceIntentInfo(Service _service) {
5020 service = _service;
5021 }
5022
5023 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005024 StringBuilder sb = new StringBuilder(128);
5025 sb.append("ServiceIntentInfo{");
5026 sb.append(Integer.toHexString(System.identityHashCode(this)));
5027 sb.append(' ');
5028 service.appendComponentShortName(sb);
5029 sb.append('}');
5030 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005031 }
5032 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005033
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005034 public static final class ProviderIntentInfo extends IntentInfo {
5035 public final Provider provider;
5036
5037 public ProviderIntentInfo(Provider provider) {
5038 this.provider = provider;
5039 }
5040
5041 public String toString() {
5042 StringBuilder sb = new StringBuilder(128);
5043 sb.append("ProviderIntentInfo{");
5044 sb.append(Integer.toHexString(System.identityHashCode(this)));
5045 sb.append(' ');
5046 provider.appendComponentShortName(sb);
5047 sb.append('}');
5048 return sb.toString();
5049 }
5050 }
5051
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005052 /**
5053 * @hide
5054 */
5055 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
5056 sCompatibilityModeEnabled = compatibilityModeEnabled;
5057 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005058
Jeff Sharkey275e0852014-06-17 18:18:49 -07005059 private static AtomicReference<byte[]> sBuffer = new AtomicReference<byte[]>();
5060
5061 public static long readFullyIgnoringContents(InputStream in) throws IOException {
5062 byte[] buffer = sBuffer.getAndSet(null);
5063 if (buffer == null) {
5064 buffer = new byte[4096];
5065 }
5066
5067 int n = 0;
5068 int count = 0;
5069 while ((n = in.read(buffer, 0, buffer.length)) != -1) {
5070 count += n;
5071 }
5072
5073 sBuffer.set(buffer);
5074 return count;
5075 }
5076
5077 public static void closeQuietly(StrictJarFile jarFile) {
5078 if (jarFile != null) {
5079 try {
5080 jarFile.close();
5081 } catch (Exception ignored) {
5082 }
5083 }
5084 }
5085
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005086 public static class PackageParserException extends Exception {
5087 public final int error;
5088
5089 public PackageParserException(int error, String detailMessage) {
5090 super(detailMessage);
5091 this.error = error;
5092 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07005093
5094 public PackageParserException(int error, String detailMessage, Throwable throwable) {
5095 super(detailMessage, throwable);
5096 this.error = error;
5097 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005099}