blob: fed9261c659d8e9b9a4b9c8d2a70d2a93dedf6e3 [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 Ogunwale6dfdfd62015-04-15 12:01:38 -07003102 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
3103 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
3104 a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Craig Mautner5962b122012-10-05 14:45:52 -07003105 }
3106
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003107 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
Daniel Sandler613dde42010-06-21 13:46:39 -04003108 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
3109 }
Craig Mautner5962b122012-10-05 14:45:52 -07003110
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003111 if (sa.getBoolean(R.styleable.AndroidManifestActivity_primaryUserOnly, false)) {
Fyodor Kupolov703d1c42015-01-27 11:59:00 -08003112 a.info.flags |= ActivityInfo.FLAG_PRIMARY_USER_ONLY;
3113 }
3114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003115 if (!receiver) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003116 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07003117 hardwareAccelerated)) {
3118 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
3119 }
3120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003121 a.info.launchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003122 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
Craig Mautner2dac0562014-05-06 09:06:44 -07003123 a.info.documentLaunchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003124 R.styleable.AndroidManifestActivity_documentLaunchMode,
Craig Mautner2dac0562014-05-06 09:06:44 -07003125 ActivityInfo.DOCUMENT_LAUNCH_NONE);
Craig Mautnerffcfcaa2014-06-05 09:54:38 -07003126 a.info.maxRecents = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003127 R.styleable.AndroidManifestActivity_maxRecents,
Dianne Hackborn852975d2014-08-22 17:42:43 -07003128 ActivityManager.getDefaultAppRecentsLimitStatic());
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003129 a.info.configChanges = sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003130 a.info.softInputMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003131 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
Craig Mautner2dac0562014-05-06 09:06:44 -07003132
Craig Mautner43e52ed2014-06-16 17:18:52 -07003133 a.info.persistableMode = sa.getInteger(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003134 R.styleable.AndroidManifestActivity_persistableMode,
Craig Mautner43e52ed2014-06-16 17:18:52 -07003135 ActivityInfo.PERSIST_ROOT_ONLY);
Craig Mautner2dac0562014-05-06 09:06:44 -07003136
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003137 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07003138 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
3139 }
3140
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003141 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07003142 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
3143 }
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07003144
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003145 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07003146 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
3147 }
Dianne Hackborna4e102e2014-09-04 22:52:27 -07003148
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003149 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
Dianne Hackborna4e102e2014-09-04 22:52:27 -07003150 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
3151 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003152
3153 a.info.resizeable = sa.getBoolean(
Wale Ogunwaleabfcc222015-03-20 11:32:20 -07003154 R.styleable.AndroidManifestActivity_resizeableActivity, false);
Wale Ogunwalea9281272015-02-07 14:04:19 -08003155 if (a.info.resizeable) {
3156 // Fixed screen orientation isn't supported with resizeable activities.
3157 a.info.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3158 } else {
3159 a.info.screenOrientation = sa.getInt(
3160 R.styleable.AndroidManifestActivity_screenOrientation,
3161 ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
3162 }
Craig Mautner15df08a2015-04-01 12:17:18 -07003163
3164 a.info.lockTaskLaunchMode =
3165 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003166 } else {
3167 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
3168 a.info.configChanges = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003169
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003170 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07003171 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003172 if (a.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003173 Slog.w(TAG, "Activity exported request ignored due to singleUser: "
3174 + a.className + " at " + mArchiveSourcePath + " "
3175 + parser.getPositionDescription());
3176 a.info.exported = false;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003177 setExported = true;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003178 }
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003179 }
3180 }
3181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003182 sa.recycle();
3183
Alex Klyubinb9f8a522015-02-03 11:12:59 -08003184 if (receiver && (owner.applicationInfo.privateFlags
3185 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07003186 // A heavy-weight application can not have receives in its main process
3187 // We can do direct compare because we intern all strings.
3188 if (a.info.processName == owner.packageName) {
3189 outError[0] = "Heavy-weight applications can not have receivers in main process";
3190 }
3191 }
3192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003193 if (outError[0] != null) {
3194 return null;
3195 }
3196
3197 int outerDepth = parser.getDepth();
3198 int type;
3199 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3200 && (type != XmlPullParser.END_TAG
3201 || parser.getDepth() > outerDepth)) {
3202 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3203 continue;
3204 }
3205
3206 if (parser.getName().equals("intent-filter")) {
3207 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08003208 if (!parseIntent(res, parser, attrs, true, true, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003209 return null;
3210 }
3211 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003212 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07003213 + mArchiveSourcePath + " "
3214 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003215 } else {
3216 a.intents.add(intent);
3217 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07003218 } else if (!receiver && parser.getName().equals("preferred")) {
3219 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08003220 if (!parseIntent(res, parser, attrs, false, false, intent, outError)) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07003221 return null;
3222 }
3223 if (intent.countActions() == 0) {
3224 Slog.w(TAG, "No actions in preferred at "
3225 + mArchiveSourcePath + " "
3226 + parser.getPositionDescription());
3227 } else {
3228 if (owner.preferredActivityFilters == null) {
3229 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
3230 }
3231 owner.preferredActivityFilters.add(intent);
3232 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003233 } else if (parser.getName().equals("meta-data")) {
3234 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
3235 outError)) == null) {
3236 return null;
3237 }
3238 } else {
3239 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003240 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003241 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003242 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003243 + " at " + mArchiveSourcePath + " "
3244 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003245 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07003246 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003247 + " at " + mArchiveSourcePath + " "
3248 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003249 }
3250 XmlUtils.skipCurrentTag(parser);
3251 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003252 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07003253 if (receiver) {
3254 outError[0] = "Bad element under <receiver>: " + parser.getName();
3255 } else {
3256 outError[0] = "Bad element under <activity>: " + parser.getName();
3257 }
3258 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003259 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003260 }
3261 }
3262
3263 if (!setExported) {
3264 a.info.exported = a.intents.size() > 0;
3265 }
3266
3267 return a;
3268 }
3269
3270 private Activity parseActivityAlias(Package owner, Resources res,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003271 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
3272 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003273 TypedArray sa = res.obtainAttributes(attrs,
3274 com.android.internal.R.styleable.AndroidManifestActivityAlias);
3275
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003276 String targetActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003277 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
3278 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003279 if (targetActivity == null) {
3280 outError[0] = "<activity-alias> does not specify android:targetActivity";
3281 sa.recycle();
3282 return null;
3283 }
3284
3285 targetActivity = buildClassName(owner.applicationInfo.packageName,
3286 targetActivity, outError);
3287 if (targetActivity == null) {
3288 sa.recycle();
3289 return null;
3290 }
3291
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003292 if (mParseActivityAliasArgs == null) {
3293 mParseActivityAliasArgs = new ParseComponentArgs(owner, outError,
3294 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
3295 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
3296 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07003297 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08003298 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003299 mSeparateProcesses,
3300 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003301 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003302 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
3303 mParseActivityAliasArgs.tag = "<activity-alias>";
3304 }
3305
3306 mParseActivityAliasArgs.sa = sa;
3307 mParseActivityAliasArgs.flags = flags;
3308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003309 Activity target = null;
3310
3311 final int NA = owner.activities.size();
3312 for (int i=0; i<NA; i++) {
3313 Activity t = owner.activities.get(i);
3314 if (targetActivity.equals(t.info.name)) {
3315 target = t;
3316 break;
3317 }
3318 }
3319
3320 if (target == null) {
3321 outError[0] = "<activity-alias> target activity " + targetActivity
3322 + " not found in manifest";
3323 sa.recycle();
3324 return null;
3325 }
3326
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003327 ActivityInfo info = new ActivityInfo();
3328 info.targetActivity = targetActivity;
3329 info.configChanges = target.info.configChanges;
3330 info.flags = target.info.flags;
3331 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07003332 info.logo = target.info.logo;
Jose Limaf78e3122014-03-06 12:13:15 -08003333 info.banner = target.info.banner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003334 info.labelRes = target.info.labelRes;
3335 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
3336 info.launchMode = target.info.launchMode;
3337 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003338 if (info.descriptionRes == 0) {
3339 info.descriptionRes = target.info.descriptionRes;
3340 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003341 info.screenOrientation = target.info.screenOrientation;
3342 info.taskAffinity = target.info.taskAffinity;
3343 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07003344 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07003345 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07003346 info.parentActivityName = target.info.parentActivityName;
Craig Mautner8307ea72014-09-11 15:03:53 -07003347 info.maxRecents = target.info.maxRecents;
3348
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003349 Activity a = new Activity(mParseActivityAliasArgs, info);
3350 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003351 sa.recycle();
3352 return null;
3353 }
3354
3355 final boolean setExported = sa.hasValue(
3356 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
3357 if (setExported) {
3358 a.info.exported = sa.getBoolean(
3359 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
3360 }
3361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003362 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003363 str = sa.getNonConfigurationString(
3364 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 if (str != null) {
3366 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
3367 }
3368
Adam Powelldd8fab22012-03-22 17:47:27 -07003369 String parentName = sa.getNonConfigurationString(
3370 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003371 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07003372 if (parentName != null) {
3373 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
3374 if (outError[0] == null) {
3375 a.info.parentActivityName = parentClassName;
3376 } else {
3377 Log.e(TAG, "Activity alias " + a.info.name +
3378 " specified invalid parentActivityName " + parentName);
3379 outError[0] = null;
3380 }
3381 }
3382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003383 sa.recycle();
3384
3385 if (outError[0] != null) {
3386 return null;
3387 }
3388
3389 int outerDepth = parser.getDepth();
3390 int type;
3391 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3392 && (type != XmlPullParser.END_TAG
3393 || parser.getDepth() > outerDepth)) {
3394 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3395 continue;
3396 }
3397
3398 if (parser.getName().equals("intent-filter")) {
3399 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08003400 if (!parseIntent(res, parser, attrs, true, true, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003401 return null;
3402 }
3403 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003404 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07003405 + mArchiveSourcePath + " "
3406 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003407 } else {
3408 a.intents.add(intent);
3409 }
3410 } else if (parser.getName().equals("meta-data")) {
3411 if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData,
3412 outError)) == null) {
3413 return null;
3414 }
3415 } else {
3416 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003417 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003418 + " at " + mArchiveSourcePath + " "
3419 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003420 XmlUtils.skipCurrentTag(parser);
3421 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003422 } else {
3423 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
3424 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426 }
3427 }
3428
3429 if (!setExported) {
3430 a.info.exported = a.intents.size() > 0;
3431 }
3432
3433 return a;
3434 }
3435
3436 private Provider parseProvider(Package owner, Resources res,
3437 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
3438 throws XmlPullParserException, IOException {
3439 TypedArray sa = res.obtainAttributes(attrs,
3440 com.android.internal.R.styleable.AndroidManifestProvider);
3441
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003442 if (mParseProviderArgs == null) {
3443 mParseProviderArgs = new ParseComponentArgs(owner, outError,
3444 com.android.internal.R.styleable.AndroidManifestProvider_name,
3445 com.android.internal.R.styleable.AndroidManifestProvider_label,
3446 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07003447 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08003448 com.android.internal.R.styleable.AndroidManifestProvider_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003449 mSeparateProcesses,
3450 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003451 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003452 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
3453 mParseProviderArgs.tag = "<provider>";
3454 }
3455
3456 mParseProviderArgs.sa = sa;
3457 mParseProviderArgs.flags = flags;
3458
3459 Provider p = new Provider(mParseProviderArgs, new ProviderInfo());
3460 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003461 sa.recycle();
3462 return null;
3463 }
3464
Nick Kralevichf097b162012-07-28 12:43:48 -07003465 boolean providerExportedDefault = false;
3466
3467 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
3468 // For compatibility, applications targeting API level 16 or lower
3469 // should have their content providers exported by default, unless they
3470 // specify otherwise.
3471 providerExportedDefault = true;
3472 }
3473
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003474 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07003475 com.android.internal.R.styleable.AndroidManifestProvider_exported,
3476 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003477
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003478 String cpname = sa.getNonConfigurationString(
3479 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003480
3481 p.info.isSyncable = sa.getBoolean(
3482 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
3483 false);
3484
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003485 String permission = sa.getNonConfigurationString(
3486 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
3487 String str = sa.getNonConfigurationString(
3488 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003489 if (str == null) {
3490 str = permission;
3491 }
3492 if (str == null) {
3493 p.info.readPermission = owner.applicationInfo.permission;
3494 } else {
3495 p.info.readPermission =
3496 str.length() > 0 ? str.toString().intern() : null;
3497 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003498 str = sa.getNonConfigurationString(
3499 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003500 if (str == null) {
3501 str = permission;
3502 }
3503 if (str == null) {
3504 p.info.writePermission = owner.applicationInfo.permission;
3505 } else {
3506 p.info.writePermission =
3507 str.length() > 0 ? str.toString().intern() : null;
3508 }
3509
3510 p.info.grantUriPermissions = sa.getBoolean(
3511 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
3512 false);
3513
3514 p.info.multiprocess = sa.getBoolean(
3515 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
3516 false);
3517
3518 p.info.initOrder = sa.getInt(
3519 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
3520 0);
3521
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003522 p.info.flags = 0;
3523
3524 if (sa.getBoolean(
3525 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
3526 false)) {
3527 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003528 if (p.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003529 Slog.w(TAG, "Provider exported request ignored due to singleUser: "
3530 + p.className + " at " + mArchiveSourcePath + " "
3531 + parser.getPositionDescription());
3532 p.info.exported = false;
3533 }
3534 }
3535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003536 sa.recycle();
3537
Alex Klyubinb9f8a522015-02-03 11:12:59 -08003538 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
3539 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07003540 // A heavy-weight application can not have providers in its main process
3541 // We can do direct compare because we intern all strings.
3542 if (p.info.processName == owner.packageName) {
3543 outError[0] = "Heavy-weight applications can not have providers in main process";
3544 return null;
3545 }
3546 }
3547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003548 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07003549 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003550 return null;
3551 }
Dianne Hackborn1bc177c2014-12-03 10:20:30 -08003552 if (cpname.length() <= 0) {
3553 outError[0] = "<provider> has empty authorities attribute";
3554 return null;
3555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003556 p.info.authority = cpname.intern();
3557
3558 if (!parseProviderTags(res, parser, attrs, p, outError)) {
3559 return null;
3560 }
3561
3562 return p;
3563 }
3564
3565 private boolean parseProviderTags(Resources res,
3566 XmlPullParser parser, AttributeSet attrs,
3567 Provider outInfo, String[] outError)
3568 throws XmlPullParserException, IOException {
3569 int outerDepth = parser.getDepth();
3570 int type;
3571 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3572 && (type != XmlPullParser.END_TAG
3573 || parser.getDepth() > outerDepth)) {
3574 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3575 continue;
3576 }
3577
Jeff Sharkey85f5f812013-10-07 10:16:12 -07003578 if (parser.getName().equals("intent-filter")) {
3579 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08003580 if (!parseIntent(res, parser, attrs, true, false, intent, outError)) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07003581 return false;
3582 }
3583 outInfo.intents.add(intent);
3584
3585 } else if (parser.getName().equals("meta-data")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003586 if ((outInfo.metaData=parseMetaData(res, parser, attrs,
3587 outInfo.metaData, outError)) == null) {
3588 return false;
3589 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003591 } else if (parser.getName().equals("grant-uri-permission")) {
3592 TypedArray sa = res.obtainAttributes(attrs,
3593 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
3594
3595 PatternMatcher pa = null;
3596
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003597 String str = sa.getNonConfigurationString(
3598 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003599 if (str != null) {
3600 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
3601 }
3602
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003603 str = sa.getNonConfigurationString(
3604 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003605 if (str != null) {
3606 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
3607 }
3608
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003609 str = sa.getNonConfigurationString(
3610 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003611 if (str != null) {
3612 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
3613 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003615 sa.recycle();
3616
3617 if (pa != null) {
3618 if (outInfo.info.uriPermissionPatterns == null) {
3619 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
3620 outInfo.info.uriPermissionPatterns[0] = pa;
3621 } else {
3622 final int N = outInfo.info.uriPermissionPatterns.length;
3623 PatternMatcher[] newp = new PatternMatcher[N+1];
3624 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
3625 newp[N] = pa;
3626 outInfo.info.uriPermissionPatterns = newp;
3627 }
3628 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003629 } else {
3630 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003631 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003632 + parser.getName() + " at " + mArchiveSourcePath + " "
3633 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003634 XmlUtils.skipCurrentTag(parser);
3635 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003636 } else {
3637 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
3638 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003639 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003640 }
3641 XmlUtils.skipCurrentTag(parser);
3642
3643 } else if (parser.getName().equals("path-permission")) {
3644 TypedArray sa = res.obtainAttributes(attrs,
3645 com.android.internal.R.styleable.AndroidManifestPathPermission);
3646
3647 PathPermission pa = null;
3648
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003649 String permission = sa.getNonConfigurationString(
3650 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
3651 String readPermission = sa.getNonConfigurationString(
3652 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003653 if (readPermission == null) {
3654 readPermission = permission;
3655 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003656 String writePermission = sa.getNonConfigurationString(
3657 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003658 if (writePermission == null) {
3659 writePermission = permission;
3660 }
3661
3662 boolean havePerm = false;
3663 if (readPermission != null) {
3664 readPermission = readPermission.intern();
3665 havePerm = true;
3666 }
3667 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00003668 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003669 havePerm = true;
3670 }
3671
3672 if (!havePerm) {
3673 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003674 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003675 + parser.getName() + " at " + mArchiveSourcePath + " "
3676 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003677 XmlUtils.skipCurrentTag(parser);
3678 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003679 } else {
3680 outError[0] = "No readPermission or writePermssion for <path-permission>";
3681 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003682 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003683 }
3684
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003685 String path = sa.getNonConfigurationString(
3686 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003687 if (path != null) {
3688 pa = new PathPermission(path,
3689 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
3690 }
3691
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003692 path = sa.getNonConfigurationString(
3693 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003694 if (path != null) {
3695 pa = new PathPermission(path,
3696 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
3697 }
3698
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003699 path = sa.getNonConfigurationString(
3700 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003701 if (path != null) {
3702 pa = new PathPermission(path,
3703 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
3704 }
3705
3706 sa.recycle();
3707
3708 if (pa != null) {
3709 if (outInfo.info.pathPermissions == null) {
3710 outInfo.info.pathPermissions = new PathPermission[1];
3711 outInfo.info.pathPermissions[0] = pa;
3712 } else {
3713 final int N = outInfo.info.pathPermissions.length;
3714 PathPermission[] newp = new PathPermission[N+1];
3715 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
3716 newp[N] = pa;
3717 outInfo.info.pathPermissions = newp;
3718 }
3719 } else {
3720 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003721 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003722 + parser.getName() + " at " + mArchiveSourcePath + " "
3723 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07003724 XmlUtils.skipCurrentTag(parser);
3725 continue;
3726 }
3727 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
3728 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003729 }
3730 XmlUtils.skipCurrentTag(parser);
3731
3732 } else {
3733 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003734 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003735 + parser.getName() + " at " + mArchiveSourcePath + " "
3736 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003737 XmlUtils.skipCurrentTag(parser);
3738 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003739 } else {
3740 outError[0] = "Bad element under <provider>: " + parser.getName();
3741 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003742 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003743 }
3744 }
3745 return true;
3746 }
3747
3748 private Service parseService(Package owner, Resources res,
3749 XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
3750 throws XmlPullParserException, IOException {
3751 TypedArray sa = res.obtainAttributes(attrs,
3752 com.android.internal.R.styleable.AndroidManifestService);
3753
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003754 if (mParseServiceArgs == null) {
3755 mParseServiceArgs = new ParseComponentArgs(owner, outError,
3756 com.android.internal.R.styleable.AndroidManifestService_name,
3757 com.android.internal.R.styleable.AndroidManifestService_label,
3758 com.android.internal.R.styleable.AndroidManifestService_icon,
Adam Powell81cd2e92010-04-21 16:35:18 -07003759 com.android.internal.R.styleable.AndroidManifestService_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08003760 com.android.internal.R.styleable.AndroidManifestService_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003761 mSeparateProcesses,
3762 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003763 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003764 com.android.internal.R.styleable.AndroidManifestService_enabled);
3765 mParseServiceArgs.tag = "<service>";
3766 }
3767
3768 mParseServiceArgs.sa = sa;
3769 mParseServiceArgs.flags = flags;
3770
3771 Service s = new Service(mParseServiceArgs, new ServiceInfo());
3772 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003773 sa.recycle();
3774 return null;
3775 }
3776
Dianne Hackbornb4163a62012-08-02 18:31:26 -07003777 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003778 com.android.internal.R.styleable.AndroidManifestService_exported);
3779 if (setExported) {
3780 s.info.exported = sa.getBoolean(
3781 com.android.internal.R.styleable.AndroidManifestService_exported, false);
3782 }
3783
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003784 String str = sa.getNonConfigurationString(
3785 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003786 if (str == null) {
3787 s.info.permission = owner.applicationInfo.permission;
3788 } else {
3789 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
3790 }
3791
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003792 s.info.flags = 0;
3793 if (sa.getBoolean(
3794 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
3795 false)) {
3796 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
3797 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08003798 if (sa.getBoolean(
3799 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
3800 false)) {
3801 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
3802 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07003803 if (sa.getBoolean(
3804 com.android.internal.R.styleable.AndroidManifestService_singleUser,
3805 false)) {
3806 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003807 if (s.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackbornb4163a62012-08-02 18:31:26 -07003808 Slog.w(TAG, "Service exported request ignored due to singleUser: "
3809 + s.className + " at " + mArchiveSourcePath + " "
3810 + parser.getPositionDescription());
3811 s.info.exported = false;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003812 setExported = true;
Dianne Hackbornb4163a62012-08-02 18:31:26 -07003813 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07003814 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003816 sa.recycle();
3817
Alex Klyubinb9f8a522015-02-03 11:12:59 -08003818 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
3819 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07003820 // A heavy-weight application can not have services in its main process
3821 // We can do direct compare because we intern all strings.
3822 if (s.info.processName == owner.packageName) {
3823 outError[0] = "Heavy-weight applications can not have services in main process";
3824 return null;
3825 }
3826 }
3827
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003828 int outerDepth = parser.getDepth();
3829 int type;
3830 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3831 && (type != XmlPullParser.END_TAG
3832 || parser.getDepth() > outerDepth)) {
3833 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3834 continue;
3835 }
3836
3837 if (parser.getName().equals("intent-filter")) {
3838 ServiceIntentInfo intent = new ServiceIntentInfo(s);
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08003839 if (!parseIntent(res, parser, attrs, true, false, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003840 return null;
3841 }
3842
3843 s.intents.add(intent);
3844 } else if (parser.getName().equals("meta-data")) {
3845 if ((s.metaData=parseMetaData(res, parser, attrs, s.metaData,
3846 outError)) == null) {
3847 return null;
3848 }
3849 } else {
3850 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003851 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003852 + parser.getName() + " at " + mArchiveSourcePath + " "
3853 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003854 XmlUtils.skipCurrentTag(parser);
3855 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003856 } else {
3857 outError[0] = "Bad element under <service>: " + parser.getName();
3858 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003859 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003860 }
3861 }
3862
3863 if (!setExported) {
3864 s.info.exported = s.intents.size() > 0;
3865 }
3866
3867 return s;
3868 }
3869
3870 private boolean parseAllMetaData(Resources res,
3871 XmlPullParser parser, AttributeSet attrs, String tag,
3872 Component outInfo, String[] outError)
3873 throws XmlPullParserException, IOException {
3874 int outerDepth = parser.getDepth();
3875 int type;
3876 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3877 && (type != XmlPullParser.END_TAG
3878 || parser.getDepth() > outerDepth)) {
3879 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3880 continue;
3881 }
3882
3883 if (parser.getName().equals("meta-data")) {
3884 if ((outInfo.metaData=parseMetaData(res, parser, attrs,
3885 outInfo.metaData, outError)) == null) {
3886 return false;
3887 }
3888 } else {
3889 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003890 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003891 + parser.getName() + " at " + mArchiveSourcePath + " "
3892 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003893 XmlUtils.skipCurrentTag(parser);
3894 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003895 } else {
3896 outError[0] = "Bad element under " + tag + ": " + parser.getName();
3897 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003898 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003899 }
3900 }
3901 return true;
3902 }
3903
3904 private Bundle parseMetaData(Resources res,
3905 XmlPullParser parser, AttributeSet attrs,
3906 Bundle data, String[] outError)
3907 throws XmlPullParserException, IOException {
3908
3909 TypedArray sa = res.obtainAttributes(attrs,
3910 com.android.internal.R.styleable.AndroidManifestMetaData);
3911
3912 if (data == null) {
3913 data = new Bundle();
3914 }
3915
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003916 String name = sa.getNonConfigurationString(
3917 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003918 if (name == null) {
3919 outError[0] = "<meta-data> requires an android:name attribute";
3920 sa.recycle();
3921 return null;
3922 }
3923
Dianne Hackborn854060af2009-07-09 18:14:31 -07003924 name = name.intern();
3925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003926 TypedValue v = sa.peekValue(
3927 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
3928 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003929 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003930 data.putInt(name, v.resourceId);
3931 } else {
3932 v = sa.peekValue(
3933 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07003934 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003935 if (v != null) {
3936 if (v.type == TypedValue.TYPE_STRING) {
3937 CharSequence cs = v.coerceToString();
Dianne Hackborn854060af2009-07-09 18:14:31 -07003938 data.putString(name, cs != null ? cs.toString().intern() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003939 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
3940 data.putBoolean(name, v.data != 0);
3941 } else if (v.type >= TypedValue.TYPE_FIRST_INT
3942 && v.type <= TypedValue.TYPE_LAST_INT) {
3943 data.putInt(name, v.data);
3944 } else if (v.type == TypedValue.TYPE_FLOAT) {
3945 data.putFloat(name, v.getFloat());
3946 } else {
3947 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003948 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003949 + parser.getName() + " at " + mArchiveSourcePath + " "
3950 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003951 } else {
3952 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
3953 data = null;
3954 }
3955 }
3956 } else {
3957 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
3958 data = null;
3959 }
3960 }
3961
3962 sa.recycle();
3963
3964 XmlUtils.skipCurrentTag(parser);
3965
3966 return data;
3967 }
3968
Kenny Root05ca4c92011-09-15 10:36:25 -07003969 private static VerifierInfo parseVerifier(Resources res, XmlPullParser parser,
Jeff Sharkey275e0852014-06-17 18:18:49 -07003970 AttributeSet attrs, int flags) {
Kenny Root05ca4c92011-09-15 10:36:25 -07003971 final TypedArray sa = res.obtainAttributes(attrs,
3972 com.android.internal.R.styleable.AndroidManifestPackageVerifier);
3973
3974 final String packageName = sa.getNonResourceString(
3975 com.android.internal.R.styleable.AndroidManifestPackageVerifier_name);
3976
3977 final String encodedPublicKey = sa.getNonResourceString(
3978 com.android.internal.R.styleable.AndroidManifestPackageVerifier_publicKey);
3979
3980 sa.recycle();
3981
3982 if (packageName == null || packageName.length() == 0) {
3983 Slog.i(TAG, "verifier package name was null; skipping");
3984 return null;
Kenny Root05ca4c92011-09-15 10:36:25 -07003985 }
3986
Christopher Tate30147332014-04-15 12:57:47 -07003987 final PublicKey publicKey = parsePublicKey(encodedPublicKey);
3988 if (publicKey == null) {
3989 Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
3990 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -08003991 }
3992
Christopher Tate30147332014-04-15 12:57:47 -07003993 return new VerifierInfo(packageName, publicKey);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003994 }
3995
Christopher Tate30147332014-04-15 12:57:47 -07003996 public static final PublicKey parsePublicKey(final String encodedPublicKey) {
3997 if (encodedPublicKey == null) {
3998 Slog.i(TAG, "Could not parse null public key");
3999 return null;
4000 }
4001
Kenny Root05ca4c92011-09-15 10:36:25 -07004002 EncodedKeySpec keySpec;
4003 try {
4004 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
4005 keySpec = new X509EncodedKeySpec(encoded);
4006 } catch (IllegalArgumentException e) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08004007 Slog.i(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07004008 return null;
4009 }
4010
4011 /* First try the key as an RSA key. */
4012 try {
4013 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08004014 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07004015 } catch (NoSuchAlgorithmException e) {
4016 Log.wtf(TAG, "Could not parse public key because RSA isn't included in build");
4017 return null;
4018 } catch (InvalidKeySpecException e) {
4019 // Not a RSA public key.
4020 }
4021
4022 /* Now try it as a DSA key. */
4023 try {
4024 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08004025 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07004026 } catch (NoSuchAlgorithmException e) {
4027 Log.wtf(TAG, "Could not parse public key because DSA isn't included in build");
4028 return null;
4029 } catch (InvalidKeySpecException e) {
4030 // Not a DSA public key.
4031 }
4032
4033 return null;
4034 }
4035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004036 private static final String ANDROID_RESOURCES
4037 = "http://schemas.android.com/apk/res/android";
4038
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004039 private boolean parseIntent(Resources res, XmlPullParser parser, AttributeSet attrs,
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08004040 boolean allowGlobs, boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004041 throws XmlPullParserException, IOException {
4042
4043 TypedArray sa = res.obtainAttributes(attrs,
4044 com.android.internal.R.styleable.AndroidManifestIntentFilter);
4045
4046 int priority = sa.getInt(
4047 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004048 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08004049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004050 TypedValue v = sa.peekValue(
4051 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
4052 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4053 outInfo.nonLocalizedLabel = v.coerceToString();
4054 }
4055
4056 outInfo.icon = sa.getResourceId(
4057 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
Adam Powell81cd2e92010-04-21 16:35:18 -07004058
4059 outInfo.logo = sa.getResourceId(
4060 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004061
Jose Limaf78e3122014-03-06 12:13:15 -08004062 outInfo.banner = sa.getResourceId(
4063 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
4064
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08004065 if (allowAutoVerify) {
4066 outInfo.setAutoVerify(sa.getBoolean(
4067 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
4068 false));
4069 }
4070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004071 sa.recycle();
4072
4073 int outerDepth = parser.getDepth();
4074 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07004075 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
4076 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
4077 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004078 continue;
4079 }
4080
4081 String nodeName = parser.getName();
4082 if (nodeName.equals("action")) {
4083 String value = attrs.getAttributeValue(
4084 ANDROID_RESOURCES, "name");
4085 if (value == null || value == "") {
4086 outError[0] = "No value supplied for <android:name>";
4087 return false;
4088 }
4089 XmlUtils.skipCurrentTag(parser);
4090
4091 outInfo.addAction(value);
4092 } else if (nodeName.equals("category")) {
4093 String value = attrs.getAttributeValue(
4094 ANDROID_RESOURCES, "name");
4095 if (value == null || value == "") {
4096 outError[0] = "No value supplied for <android:name>";
4097 return false;
4098 }
4099 XmlUtils.skipCurrentTag(parser);
4100
4101 outInfo.addCategory(value);
4102
4103 } else if (nodeName.equals("data")) {
4104 sa = res.obtainAttributes(attrs,
4105 com.android.internal.R.styleable.AndroidManifestData);
4106
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004107 String str = sa.getNonConfigurationString(
4108 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004109 if (str != null) {
4110 try {
4111 outInfo.addDataType(str);
4112 } catch (IntentFilter.MalformedMimeTypeException e) {
4113 outError[0] = e.toString();
4114 sa.recycle();
4115 return false;
4116 }
4117 }
4118
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004119 str = sa.getNonConfigurationString(
4120 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004121 if (str != null) {
4122 outInfo.addDataScheme(str);
4123 }
4124
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07004125 str = sa.getNonConfigurationString(
4126 com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
4127 if (str != null) {
4128 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
4129 }
4130
4131 str = sa.getNonConfigurationString(
4132 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
4133 if (str != null) {
4134 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
4135 }
4136
4137 str = sa.getNonConfigurationString(
4138 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
4139 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004140 if (!allowGlobs) {
4141 outError[0] = "sspPattern not allowed here; ssp must be literal";
4142 return false;
4143 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07004144 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4145 }
4146
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004147 String host = sa.getNonConfigurationString(
4148 com.android.internal.R.styleable.AndroidManifestData_host, 0);
4149 String port = sa.getNonConfigurationString(
4150 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004151 if (host != null) {
4152 outInfo.addDataAuthority(host, port);
4153 }
4154
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004155 str = sa.getNonConfigurationString(
4156 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004157 if (str != null) {
4158 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
4159 }
4160
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004161 str = sa.getNonConfigurationString(
4162 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004163 if (str != null) {
4164 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
4165 }
4166
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004167 str = sa.getNonConfigurationString(
4168 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004169 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004170 if (!allowGlobs) {
4171 outError[0] = "pathPattern not allowed here; path must be literal";
4172 return false;
4173 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004174 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4175 }
4176
4177 sa.recycle();
4178 XmlUtils.skipCurrentTag(parser);
4179 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004180 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004181 + parser.getName() + " at " + mArchiveSourcePath + " "
4182 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004183 XmlUtils.skipCurrentTag(parser);
4184 } else {
4185 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
4186 return false;
4187 }
4188 }
4189
4190 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07004191
4192 if (DEBUG_PARSER) {
4193 final StringBuilder cats = new StringBuilder("Intent d=");
4194 cats.append(outInfo.hasDefault);
4195 cats.append(", cat=");
4196
4197 final Iterator<String> it = outInfo.categoriesIterator();
4198 if (it != null) {
4199 while (it.hasNext()) {
4200 cats.append(' ');
4201 cats.append(it.next());
4202 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004203 }
Kenny Rootd2d29252011-08-08 11:27:57 -07004204 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004205 }
4206
4207 return true;
4208 }
4209
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004210 /**
4211 * Representation of a full package parsed from APK files on disk. A package
4212 * consists of a single base APK, and zero or more split APKs.
4213 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004214 public final static class Package {
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07004215
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004216 public String packageName;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004217
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004218 /** Names of any split APKs, ordered by parsed splitName */
4219 public String[] splitNames;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004220
4221 // TODO: work towards making these paths invariant
Jeff Sharkey275e0852014-06-17 18:18:49 -07004222
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07004223 public String volumeUuid;
4224
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004225 /**
4226 * Path where this package was found on disk. For monolithic packages
4227 * this is path to single base APK file; for cluster packages this is
4228 * path to the cluster directory.
4229 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004230 public String codePath;
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004231
4232 /** Path of base APK */
4233 public String baseCodePath;
4234 /** Paths of any split APKs, ordered by parsed splitName */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004235 public String[] splitCodePaths;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004236
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004237 /** Revision code of base APK */
4238 public int baseRevisionCode;
4239 /** Revision codes of any split APKs, ordered by parsed splitName */
4240 public int[] splitRevisionCodes;
4241
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004242 /** Flags of any split APKs; ordered by parsed splitName */
4243 public int[] splitFlags;
4244
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004245 /**
4246 * Private flags of any split APKs; ordered by parsed splitName.
4247 *
4248 * {@hide}
4249 */
4250 public int[] splitPrivateFlags;
4251
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004252 public boolean baseHardwareAccelerated;
4253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004254 // For now we only support one application per package.
4255 public final ApplicationInfo applicationInfo = new ApplicationInfo();
4256
4257 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
4258 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
4259 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
4260 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
4261 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
4262 public final ArrayList<Service> services = new ArrayList<Service>(0);
4263 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
4264
4265 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
4266
Dianne Hackborn854060af2009-07-09 18:14:31 -07004267 public ArrayList<String> protectedBroadcasts;
Dianne Hackbornc895be72013-03-11 17:48:43 -07004268
4269 public ArrayList<String> libraryNames = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07004270 public ArrayList<String> usesLibraries = null;
4271 public ArrayList<String> usesOptionalLibraries = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004272 public String[] usesLibraryFiles = null;
4273
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004274 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
4275
Dianne Hackbornc1552392010-03-03 16:19:01 -08004276 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004277 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08004278 public ArrayList<String> mAdoptPermissions = null;
4279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004280 // We store the application meta-data independently to avoid multiple unwanted references
4281 public Bundle mAppMetaData = null;
4282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004283 // The version code declared for this package.
4284 public int mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004286 // The version name declared for this package.
4287 public String mVersionName;
4288
4289 // The shared user id that this package wants to use.
4290 public String mSharedUserId;
4291
4292 // The shared user label that this package wants to use.
4293 public int mSharedUserLabel;
4294
4295 // Signatures that were read from the package.
Jeff Sharkey275e0852014-06-17 18:18:49 -07004296 public Signature[] mSignatures;
4297 public Certificate[][] mCertificates;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004298
4299 // For use by package manager service for quick lookup of
4300 // preferred up order.
4301 public int mPreferredOrder = 0;
4302
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07004303 // For use by package manager to keep track of where it needs to do dexopt.
Narayan Kamath20531682014-07-14 13:18:43 +01004304 public final ArraySet<String> mDexOptPerformed = new ArraySet<>(4);
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07004305
4306 // For use by package manager to keep track of when a package was last used.
4307 public long mLastPackageUsageTimeInMills;
4308
Amith Yamasani13593602012-03-22 16:16:17 -07004309 // // User set enabled state.
4310 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
4311 //
4312 // // Whether the package has been stopped.
4313 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004315 // Additional data supplied by callers.
4316 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07004317
4318 // Whether an operation is currently pending on this package
4319 public boolean mOperationPending;
4320
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004321 // Applications hardware preferences
4322 public ArrayList<ConfigurationInfo> configPreferences = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004323
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004324 // Applications requested features
Dianne Hackborn49237342009-08-27 20:08:01 -07004325 public ArrayList<FeatureInfo> reqFeatures = null;
4326
Adam Lesinskid3edfde2014-08-08 17:32:44 -07004327 // Applications requested feature groups
4328 public ArrayList<FeatureGroupInfo> featureGroups = null;
4329
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08004330 public int installLocation;
4331
Jeff Hao272bf3a2014-10-08 13:34:43 -07004332 public boolean coreApp;
4333
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08004334 /* An app that's required for all users and cannot be uninstalled for a user */
4335 public boolean mRequiredForAllUsers;
4336
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07004337 /* The restricted account authenticator type that is used by this application */
4338 public String mRestrictedAccountType;
4339
Amith Yamasaniccbe3892013-04-12 17:52:42 -07004340 /* The required account type without which this application will not function */
4341 public String mRequiredAccountType;
4342
Kenny Rootbcc954d2011-08-08 16:19:08 -07004343 /**
4344 * Digest suitable for comparing whether this package's manifest is the
4345 * same as another.
4346 */
4347 public ManifestDigest manifestDigest;
4348
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01004349 public String mOverlayTarget;
4350 public int mOverlayPriority;
4351 public boolean mTrustedOverlay;
4352
Geremy Condraf1bcca82013-01-07 22:35:24 -08004353 /**
dcashman989eb3712014-06-17 12:56:12 -07004354 * Data used to feed the KeySetManagerService
Geremy Condraf1bcca82013-01-07 22:35:24 -08004355 */
dcashman989eb3712014-06-17 12:56:12 -07004356 public ArraySet<PublicKey> mSigningKeys;
4357 public ArraySet<String> mUpgradeKeySets;
4358 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -08004359
Narayan Kamath4903f642014-08-11 13:33:45 +01004360 /**
4361 * The install time abi override for this package, if any.
4362 *
4363 * TODO: This seems like a horrible place to put the abiOverride because
4364 * this isn't something the packageParser parsers. However, this fits in with
4365 * the rest of the PackageManager where package scanning randomly pushes
4366 * and prods fields out of {@code this.applicationInfo}.
4367 */
4368 public String cpuAbiOverride;
4369
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004370 public Package(String packageName) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07004371 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07004372 applicationInfo.packageName = packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004373 applicationInfo.uid = -1;
4374 }
4375
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004376 public List<String> getAllCodePaths() {
Jeff Sharkey275e0852014-06-17 18:18:49 -07004377 ArrayList<String> paths = new ArrayList<>();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004378 paths.add(baseCodePath);
Jeff Sharkey275e0852014-06-17 18:18:49 -07004379 if (!ArrayUtils.isEmpty(splitCodePaths)) {
4380 Collections.addAll(paths, splitCodePaths);
4381 }
4382 return paths;
4383 }
4384
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004385 /**
4386 * Filtered set of {@link #getAllCodePaths()} that excludes
4387 * resource-only APKs.
4388 */
4389 public List<String> getAllCodePathsExcludingResourceOnly() {
4390 ArrayList<String> paths = new ArrayList<>();
4391 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
4392 paths.add(baseCodePath);
4393 }
4394 if (!ArrayUtils.isEmpty(splitCodePaths)) {
4395 for (int i = 0; i < splitCodePaths.length; i++) {
4396 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
4397 paths.add(splitCodePaths[i]);
4398 }
4399 }
4400 }
4401 return paths;
4402 }
4403
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004404 public void setPackageName(String newName) {
4405 packageName = newName;
4406 applicationInfo.packageName = newName;
4407 for (int i=permissions.size()-1; i>=0; i--) {
4408 permissions.get(i).setPackageName(newName);
4409 }
4410 for (int i=permissionGroups.size()-1; i>=0; i--) {
4411 permissionGroups.get(i).setPackageName(newName);
4412 }
4413 for (int i=activities.size()-1; i>=0; i--) {
4414 activities.get(i).setPackageName(newName);
4415 }
4416 for (int i=receivers.size()-1; i>=0; i--) {
4417 receivers.get(i).setPackageName(newName);
4418 }
4419 for (int i=providers.size()-1; i>=0; i--) {
4420 providers.get(i).setPackageName(newName);
4421 }
4422 for (int i=services.size()-1; i>=0; i--) {
4423 services.get(i).setPackageName(newName);
4424 }
4425 for (int i=instrumentation.size()-1; i>=0; i--) {
4426 instrumentation.get(i).setPackageName(newName);
4427 }
4428 }
Dianne Hackborn65696252012-03-05 18:49:21 -08004429
4430 public boolean hasComponentClassName(String name) {
4431 for (int i=activities.size()-1; i>=0; i--) {
4432 if (name.equals(activities.get(i).className)) {
4433 return true;
4434 }
4435 }
4436 for (int i=receivers.size()-1; i>=0; i--) {
4437 if (name.equals(receivers.get(i).className)) {
4438 return true;
4439 }
4440 }
4441 for (int i=providers.size()-1; i>=0; i--) {
4442 if (name.equals(providers.get(i).className)) {
4443 return true;
4444 }
4445 }
4446 for (int i=services.size()-1; i>=0; i--) {
4447 if (name.equals(services.get(i).className)) {
4448 return true;
4449 }
4450 }
4451 for (int i=instrumentation.size()-1; i>=0; i--) {
4452 if (name.equals(instrumentation.get(i).className)) {
4453 return true;
4454 }
4455 }
4456 return false;
4457 }
4458
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08004459 /**
4460 * @hide
4461 */
4462 public boolean isForwardLocked() {
4463 return applicationInfo.isForwardLocked();
4464 }
4465
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08004466 /**
4467 * @hide
4468 */
4469 public boolean isSystemApp() {
4470 return applicationInfo.isSystemApp();
4471 }
4472
4473 /**
4474 * @hide
4475 */
4476 public boolean isUpdatedSystemApp() {
4477 return applicationInfo.isUpdatedSystemApp();
4478 }
4479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004480 public String toString() {
4481 return "Package{"
4482 + Integer.toHexString(System.identityHashCode(this))
4483 + " " + packageName + "}";
4484 }
4485 }
4486
4487 public static class Component<II extends IntentInfo> {
4488 public final Package owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004489 public final ArrayList<II> intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004490 public final String className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004491 public Bundle metaData;
4492
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004493 ComponentName componentName;
4494 String componentShortName;
4495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004496 public Component(Package _owner) {
4497 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004498 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004499 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004500 }
4501
4502 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
4503 owner = args.owner;
4504 intents = new ArrayList<II>(0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004505 String name = args.sa.getNonConfigurationString(args.nameRes, 0);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004506 if (name == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004507 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004508 args.outError[0] = args.tag + " does not specify android:name";
4509 return;
4510 }
4511
4512 outInfo.name
4513 = buildClassName(owner.applicationInfo.packageName, name, args.outError);
4514 if (outInfo.name == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004515 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004516 args.outError[0] = args.tag + " does not have valid android:name";
4517 return;
4518 }
4519
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004520 className = outInfo.name;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004521
4522 int iconVal = args.sa.getResourceId(args.iconRes, 0);
4523 if (iconVal != 0) {
4524 outInfo.icon = iconVal;
4525 outInfo.nonLocalizedLabel = null;
4526 }
Adam Powell81cd2e92010-04-21 16:35:18 -07004527
4528 int logoVal = args.sa.getResourceId(args.logoRes, 0);
4529 if (logoVal != 0) {
4530 outInfo.logo = logoVal;
4531 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004532
Jose Limaf78e3122014-03-06 12:13:15 -08004533 int bannerVal = args.sa.getResourceId(args.bannerRes, 0);
4534 if (bannerVal != 0) {
4535 outInfo.banner = bannerVal;
4536 }
4537
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004538 TypedValue v = args.sa.peekValue(args.labelRes);
4539 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4540 outInfo.nonLocalizedLabel = v.coerceToString();
4541 }
4542
4543 outInfo.packageName = owner.packageName;
4544 }
4545
4546 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
4547 this(args, (PackageItemInfo)outInfo);
4548 if (args.outError[0] != null) {
4549 return;
4550 }
4551
4552 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07004553 CharSequence pname;
4554 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004555 pname = args.sa.getNonConfigurationString(args.processRes,
4556 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07004557 } else {
4558 // Some older apps have been seen to use a resource reference
4559 // here that on older builds was ignored (with a warning). We
4560 // need to continue to do this for them so they don't break.
4561 pname = args.sa.getNonResourceString(args.processRes);
4562 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004563 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07004564 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004565 args.flags, args.sepProcesses, args.outError);
4566 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004567
4568 if (args.descriptionRes != 0) {
4569 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
4570 }
4571
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004572 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004573 }
4574
4575 public Component(Component<II> clone) {
4576 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004577 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004578 className = clone.className;
4579 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004580 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004581 }
4582
4583 public ComponentName getComponentName() {
4584 if (componentName != null) {
4585 return componentName;
4586 }
4587 if (className != null) {
4588 componentName = new ComponentName(owner.applicationInfo.packageName,
4589 className);
4590 }
4591 return componentName;
4592 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07004593
4594 public void appendComponentShortName(StringBuilder sb) {
4595 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004596 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07004597
4598 public void printComponentShortName(PrintWriter pw) {
4599 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
4600 }
4601
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004602 public void setPackageName(String packageName) {
4603 componentName = null;
4604 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004605 }
4606 }
4607
4608 public final static class Permission extends Component<IntentInfo> {
4609 public final PermissionInfo info;
4610 public boolean tree;
4611 public PermissionGroup group;
4612
4613 public Permission(Package _owner) {
4614 super(_owner);
4615 info = new PermissionInfo();
4616 }
4617
4618 public Permission(Package _owner, PermissionInfo _info) {
4619 super(_owner);
4620 info = _info;
4621 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004622
4623 public void setPackageName(String packageName) {
4624 super.setPackageName(packageName);
4625 info.packageName = packageName;
4626 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004627
4628 public String toString() {
4629 return "Permission{"
4630 + Integer.toHexString(System.identityHashCode(this))
4631 + " " + info.name + "}";
4632 }
4633 }
4634
4635 public final static class PermissionGroup extends Component<IntentInfo> {
4636 public final PermissionGroupInfo info;
4637
4638 public PermissionGroup(Package _owner) {
4639 super(_owner);
4640 info = new PermissionGroupInfo();
4641 }
4642
4643 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
4644 super(_owner);
4645 info = _info;
4646 }
4647
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004648 public void setPackageName(String packageName) {
4649 super.setPackageName(packageName);
4650 info.packageName = packageName;
4651 }
4652
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004653 public String toString() {
4654 return "PermissionGroup{"
4655 + Integer.toHexString(System.identityHashCode(this))
4656 + " " + info.name + "}";
4657 }
4658 }
4659
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004660 private static boolean copyNeeded(int flags, Package p,
4661 PackageUserState state, Bundle metaData, int userId) {
Amith Yamasani1742cfb2015-04-14 15:41:20 -07004662 if (userId != UserHandle.USER_OWNER) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004663 // We always need to copy for other users, since we need
4664 // to fix up the uid.
4665 return true;
4666 }
4667 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
4668 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07004669 if (p.applicationInfo.enabled != enabled) {
4670 return true;
4671 }
4672 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004673 if (!state.installed || state.hidden) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004674 return true;
4675 }
4676 if (state.stopped) {
4677 return true;
4678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004679 if ((flags & PackageManager.GET_META_DATA) != 0
4680 && (metaData != null || p.mAppMetaData != null)) {
4681 return true;
4682 }
4683 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
4684 && p.usesLibraryFiles != null) {
4685 return true;
4686 }
4687 return false;
4688 }
4689
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004690 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
4691 PackageUserState state) {
4692 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07004693 }
4694
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08004695 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
4696 PackageUserState state) {
4697 // CompatibilityMode is global state.
4698 if (!sCompatibilityModeEnabled) {
4699 ai.disableCompatibilityMode();
4700 }
4701 if (state.installed) {
4702 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
4703 } else {
4704 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
4705 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004706 if (state.hidden) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004707 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07004708 } else {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004709 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07004710 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08004711 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
4712 ai.enabled = true;
4713 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
4714 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
4715 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
4716 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
4717 ai.enabled = false;
4718 }
4719 ai.enabledSetting = state.enabled;
4720 }
4721
Amith Yamasani13593602012-03-22 16:16:17 -07004722 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004723 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004724 if (p == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004725 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004726 return null;
4727 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08004728 if (!copyNeeded(flags, p, state, null, userId)
4729 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
4730 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
4731 // In this case it is safe to directly modify the internal ApplicationInfo state:
4732 // - CompatibilityMode is global state, so will be the same for every call.
4733 // - We only come in to here if the app should reported as installed; this is the
4734 // default state, and we will do a copy otherwise.
4735 // - The enable state will always be reported the same for the application across
4736 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
4737 // be doing a copy.
4738 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004739 return p.applicationInfo;
4740 }
4741
4742 // Make shallow copy so we can store the metadata/libraries safely
4743 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Amith Yamasani1742cfb2015-04-14 15:41:20 -07004744 ai.uid = UserHandle.getUid(userId, ai.uid);
4745 ai.dataDir = PackageManager.getDataDirForUser(ai.volumeUuid, ai.packageName, userId)
4746 .getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004747 if ((flags & PackageManager.GET_META_DATA) != 0) {
4748 ai.metaData = p.mAppMetaData;
4749 }
4750 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
4751 ai.sharedLibraryFiles = p.usesLibraryFiles;
4752 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004753 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07004754 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004755 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07004756 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004757 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08004758 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004759 return ai;
4760 }
4761
Dianne Hackbornace27912014-09-18 18:38:30 -07004762 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
4763 PackageUserState state, int userId) {
4764 if (ai == null) return null;
4765 if (!checkUseInstalledOrHidden(flags, state)) {
4766 return null;
4767 }
4768 // This is only used to return the ResolverActivity; we will just always
4769 // make a copy.
4770 ai = new ApplicationInfo(ai);
Amith Yamasani1742cfb2015-04-14 15:41:20 -07004771 ai.uid = UserHandle.getUid(userId, ai.uid);
4772 ai.dataDir = PackageManager.getDataDirForUser(ai.volumeUuid, ai.packageName, userId)
4773 .getAbsolutePath();
Dianne Hackbornace27912014-09-18 18:38:30 -07004774 if (state.stopped) {
4775 ai.flags |= ApplicationInfo.FLAG_STOPPED;
4776 } else {
4777 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
4778 }
4779 updateApplicationInfo(ai, flags, state);
4780 return ai;
4781 }
4782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004783 public static final PermissionInfo generatePermissionInfo(
4784 Permission p, int flags) {
4785 if (p == null) return null;
4786 if ((flags&PackageManager.GET_META_DATA) == 0) {
4787 return p.info;
4788 }
4789 PermissionInfo pi = new PermissionInfo(p.info);
4790 pi.metaData = p.metaData;
4791 return pi;
4792 }
4793
4794 public static final PermissionGroupInfo generatePermissionGroupInfo(
4795 PermissionGroup pg, int flags) {
4796 if (pg == null) return null;
4797 if ((flags&PackageManager.GET_META_DATA) == 0) {
4798 return pg.info;
4799 }
4800 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
4801 pgi.metaData = pg.metaData;
4802 return pgi;
4803 }
4804
4805 public final static class Activity extends Component<ActivityIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004806 public final ActivityInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004807
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004808 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
4809 super(args, _info);
4810 info = _info;
4811 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004812 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004813
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004814 public void setPackageName(String packageName) {
4815 super.setPackageName(packageName);
4816 info.packageName = packageName;
4817 }
4818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004819 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07004820 StringBuilder sb = new StringBuilder(128);
4821 sb.append("Activity{");
4822 sb.append(Integer.toHexString(System.identityHashCode(this)));
4823 sb.append(' ');
4824 appendComponentShortName(sb);
4825 sb.append('}');
4826 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004827 }
4828 }
4829
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004830 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
4831 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004832 if (a == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004833 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004834 return null;
4835 }
4836 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004837 return a.info;
4838 }
4839 // Make shallow copies so we can store the metadata safely
4840 ActivityInfo ai = new ActivityInfo(a.info);
4841 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004842 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004843 return ai;
4844 }
4845
Dianne Hackbornace27912014-09-18 18:38:30 -07004846 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
4847 PackageUserState state, int userId) {
4848 if (ai == null) return null;
4849 if (!checkUseInstalledOrHidden(flags, state)) {
4850 return null;
4851 }
4852 // This is only used to return the ResolverActivity; we will just always
4853 // make a copy.
4854 ai = new ActivityInfo(ai);
4855 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
4856 return ai;
4857 }
4858
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004859 public final static class Service extends Component<ServiceIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004860 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004861
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004862 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
4863 super(args, _info);
4864 info = _info;
4865 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004866 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004867
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004868 public void setPackageName(String packageName) {
4869 super.setPackageName(packageName);
4870 info.packageName = packageName;
4871 }
4872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004873 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07004874 StringBuilder sb = new StringBuilder(128);
4875 sb.append("Service{");
4876 sb.append(Integer.toHexString(System.identityHashCode(this)));
4877 sb.append(' ');
4878 appendComponentShortName(sb);
4879 sb.append('}');
4880 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004881 }
4882 }
4883
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004884 public static final ServiceInfo generateServiceInfo(Service s, int flags,
4885 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004886 if (s == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004887 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004888 return null;
4889 }
4890 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004891 return s.info;
4892 }
4893 // Make shallow copies so we can store the metadata safely
4894 ServiceInfo si = new ServiceInfo(s.info);
4895 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004896 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004897 return si;
4898 }
4899
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004900 public final static class Provider extends Component<ProviderIntentInfo> {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004901 public final ProviderInfo info;
4902 public boolean syncable;
4903
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004904 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
4905 super(args, _info);
4906 info = _info;
4907 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004908 syncable = false;
4909 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004910
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004911 public Provider(Provider existingProvider) {
4912 super(existingProvider);
4913 this.info = existingProvider.info;
4914 this.syncable = existingProvider.syncable;
4915 }
4916
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004917 public void setPackageName(String packageName) {
4918 super.setPackageName(packageName);
4919 info.packageName = packageName;
4920 }
4921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004922 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07004923 StringBuilder sb = new StringBuilder(128);
4924 sb.append("Provider{");
4925 sb.append(Integer.toHexString(System.identityHashCode(this)));
4926 sb.append(' ');
4927 appendComponentShortName(sb);
4928 sb.append('}');
4929 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004930 }
4931 }
4932
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004933 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
4934 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004935 if (p == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004936 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004937 return null;
4938 }
4939 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004940 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004941 || p.info.uriPermissionPatterns == null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004942 return p.info;
4943 }
4944 // Make shallow copies so we can store the metadata safely
4945 ProviderInfo pi = new ProviderInfo(p.info);
4946 pi.metaData = p.metaData;
4947 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
4948 pi.uriPermissionPatterns = null;
4949 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07004950 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004951 return pi;
4952 }
4953
4954 public final static class Instrumentation extends Component {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004955 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004956
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004957 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
4958 super(args, _info);
4959 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004960 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004961
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004962 public void setPackageName(String packageName) {
4963 super.setPackageName(packageName);
4964 info.packageName = packageName;
4965 }
4966
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004967 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07004968 StringBuilder sb = new StringBuilder(128);
4969 sb.append("Instrumentation{");
4970 sb.append(Integer.toHexString(System.identityHashCode(this)));
4971 sb.append(' ');
4972 appendComponentShortName(sb);
4973 sb.append('}');
4974 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004975 }
4976 }
4977
4978 public static final InstrumentationInfo generateInstrumentationInfo(
4979 Instrumentation i, int flags) {
4980 if (i == null) return null;
4981 if ((flags&PackageManager.GET_META_DATA) == 0) {
4982 return i.info;
4983 }
4984 InstrumentationInfo ii = new InstrumentationInfo(i.info);
4985 ii.metaData = i.metaData;
4986 return ii;
4987 }
4988
4989 public static class IntentInfo extends IntentFilter {
4990 public boolean hasDefault;
4991 public int labelRes;
4992 public CharSequence nonLocalizedLabel;
4993 public int icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07004994 public int logo;
Jose Limaf78e3122014-03-06 12:13:15 -08004995 public int banner;
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004996 public int preferred;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004997 }
4998
4999 public final static class ActivityIntentInfo extends IntentInfo {
5000 public final Activity activity;
5001
5002 public ActivityIntentInfo(Activity _activity) {
5003 activity = _activity;
5004 }
5005
5006 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005007 StringBuilder sb = new StringBuilder(128);
5008 sb.append("ActivityIntentInfo{");
5009 sb.append(Integer.toHexString(System.identityHashCode(this)));
5010 sb.append(' ');
5011 activity.appendComponentShortName(sb);
5012 sb.append('}');
5013 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005014 }
5015 }
5016
5017 public final static class ServiceIntentInfo extends IntentInfo {
5018 public final Service service;
5019
5020 public ServiceIntentInfo(Service _service) {
5021 service = _service;
5022 }
5023
5024 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005025 StringBuilder sb = new StringBuilder(128);
5026 sb.append("ServiceIntentInfo{");
5027 sb.append(Integer.toHexString(System.identityHashCode(this)));
5028 sb.append(' ');
5029 service.appendComponentShortName(sb);
5030 sb.append('}');
5031 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005032 }
5033 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005034
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005035 public static final class ProviderIntentInfo extends IntentInfo {
5036 public final Provider provider;
5037
5038 public ProviderIntentInfo(Provider provider) {
5039 this.provider = provider;
5040 }
5041
5042 public String toString() {
5043 StringBuilder sb = new StringBuilder(128);
5044 sb.append("ProviderIntentInfo{");
5045 sb.append(Integer.toHexString(System.identityHashCode(this)));
5046 sb.append(' ');
5047 provider.appendComponentShortName(sb);
5048 sb.append('}');
5049 return sb.toString();
5050 }
5051 }
5052
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005053 /**
5054 * @hide
5055 */
5056 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
5057 sCompatibilityModeEnabled = compatibilityModeEnabled;
5058 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005059
Jeff Sharkey275e0852014-06-17 18:18:49 -07005060 private static AtomicReference<byte[]> sBuffer = new AtomicReference<byte[]>();
5061
5062 public static long readFullyIgnoringContents(InputStream in) throws IOException {
5063 byte[] buffer = sBuffer.getAndSet(null);
5064 if (buffer == null) {
5065 buffer = new byte[4096];
5066 }
5067
5068 int n = 0;
5069 int count = 0;
5070 while ((n = in.read(buffer, 0, buffer.length)) != -1) {
5071 count += n;
5072 }
5073
5074 sBuffer.set(buffer);
5075 return count;
5076 }
5077
5078 public static void closeQuietly(StrictJarFile jarFile) {
5079 if (jarFile != null) {
5080 try {
5081 jarFile.close();
5082 } catch (Exception ignored) {
5083 }
5084 }
5085 }
5086
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005087 public static class PackageParserException extends Exception {
5088 public final int error;
5089
5090 public PackageParserException(int error, String detailMessage) {
5091 super(detailMessage);
5092 this.error = error;
5093 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07005094
5095 public PackageParserException(int error, String detailMessage, Throwable throwable) {
5096 super(detailMessage, throwable);
5097 this.error = error;
5098 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005100}