blob: 3011a69f982572aed46344e8eb5183a37331dbb9 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.content.pm;
18
Wale Ogunwaled26176f2016-01-25 20:04:04 -080019import com.android.internal.R;
20import com.android.internal.util.ArrayUtils;
21import com.android.internal.util.XmlUtils;
22
23import org.xmlpull.v1.XmlPullParser;
24import org.xmlpull.v1.XmlPullParserException;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070025
Dianne Hackborn852975d2014-08-22 17:42:43 -070026import android.app.ActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.content.ComponentName;
28import android.content.Intent;
29import android.content.IntentFilter;
30import android.content.res.AssetManager;
31import android.content.res.Configuration;
32import android.content.res.Resources;
33import android.content.res.TypedArray;
34import android.content.res.XmlResourceParser;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -070035import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.os.Bundle;
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -070037import android.os.FileUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.os.PatternMatcher;
Todd Kennedy27c24fb2015-09-17 16:49:25 -070039import android.os.Trace;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070040import android.os.UserHandle;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -070041import android.text.TextUtils;
Jeff Sharkey275e0852014-06-17 18:18:49 -070042import android.util.ArrayMap;
43import android.util.ArraySet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.util.AttributeSet;
Kenny Root05ca4c92011-09-15 10:36:25 -070045import android.util.Base64;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.util.DisplayMetrics;
Kenny Root05ca4c92011-09-15 10:36:25 -070047import android.util.Log;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070048import android.util.Pair;
Kenny Rootd2d29252011-08-08 11:27:57 -070049import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.util.TypedValue;
Alex Klyubine4157182016-01-05 13:27:05 -080051import android.util.apk.ApkSignatureSchemeV2Verifier;
Jeff Sharkeyc5967e92016-01-07 18:50:29 -070052import android.util.jar.StrictJarFile;
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -070053import android.view.Gravity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054
55import java.io.File;
56import java.io.IOException;
57import java.io.InputStream;
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -070058import java.io.PrintWriter;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070059import java.security.GeneralSecurityException;
Kenny Root05ca4c92011-09-15 10:36:25 -070060import java.security.KeyFactory;
61import java.security.NoSuchAlgorithmException;
62import java.security.PublicKey;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import java.security.cert.Certificate;
64import java.security.cert.CertificateEncodingException;
Kenny Root05ca4c92011-09-15 10:36:25 -070065import java.security.spec.EncodedKeySpec;
66import java.security.spec.InvalidKeySpecException;
67import java.security.spec.X509EncodedKeySpec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068import java.util.ArrayList;
Dianne Hackbornffcda102014-04-24 13:06:27 -070069import java.util.Arrays;
Jeff Sharkey275e0852014-06-17 18:18:49 -070070import java.util.Collections;
71import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import java.util.Iterator;
Kenny Root05ca4c92011-09-15 10:36:25 -070073import java.util.List;
Geremy Condraf1bcca82013-01-07 22:35:24 -080074import java.util.Set;
Jeff Sharkey275e0852014-06-17 18:18:49 -070075import java.util.concurrent.atomic.AtomicReference;
Kenny Root6c918ce2013-04-02 14:04:24 -070076import java.util.zip.ZipEntry;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077
Wale Ogunwaled26176f2016-01-25 20:04:04 -080078import libcore.io.IoUtils;
79
80import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
81import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
Wale Ogunwaled829d362016-02-10 19:24:49 -080082import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
Wale Ogunwaled26176f2016-01-25 20:04:04 -080083import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
84import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
85import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
86import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Rubin Xubf67c9c2016-04-20 17:09:38 +010087import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
Wale Ogunwale6afdf912016-01-30 13:01:33 -080088import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES;
Wale Ogunwaled26176f2016-01-25 20:04:04 -080089import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
90import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
91import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
92import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
93import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
94import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
95import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
96import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
97import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
98
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099/**
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700100 * Parser for package files (APKs) on disk. This supports apps packaged either
101 * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
102 * APKs in a single directory.
103 * <p>
104 * Apps packaged as multiple APKs always consist of a single "base" APK (with a
105 * {@code null} split name) and zero or more "split" APKs (with unique split
106 * names). Any subset of those split APKs are a valid install, as long as the
107 * following constraints are met:
108 * <ul>
109 * <li>All APKs must have the exact same package name, version code, and signing
110 * certificates.
111 * <li>All APKs must have unique split names.
112 * <li>All installations must contain a single base APK.
113 * </ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700115 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116 */
117public class PackageParser {
Kenny Rootd2d29252011-08-08 11:27:57 -0700118 private static final boolean DEBUG_JAR = false;
119 private static final boolean DEBUG_PARSER = false;
120 private static final boolean DEBUG_BACKUP = false;
121
Svet Ganova7532cf2016-05-02 08:13:17 -0700122 private static final boolean MULTI_PACKAGE_APK_ENABLED = false;
Svet Ganov354cd3c2015-12-17 11:35:04 -0800123 private static final int MAX_PACKAGES_PER_APK = 5;
124
Todd Kennedy66c55532016-02-26 16:22:11 -0800125 public static final int APK_SIGNING_UNKNOWN = 0;
126 public static final int APK_SIGNING_V1 = 1;
127 public static final int APK_SIGNING_V2 = 2;
128
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700129 // TODO: switch outError users to PackageParserException
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700130 // TODO: refactor "codePath" to "apkPath"
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700131
Kenny Rootbcc954d2011-08-08 16:19:08 -0700132 /** File name in an APK for the Android manifest. */
133 private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
134
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700135 /** Path prefix for apps on expanded storage */
136 private static final String MNT_EXPAND = "/mnt/expand/";
137
Svet Ganov354cd3c2015-12-17 11:35:04 -0800138 private static final String TAG_MANIFEST = "manifest";
139 private static final String TAG_APPLICATION = "application";
140 private static final String TAG_OVERLAY = "overlay";
141 private static final String TAG_KEY_SETS = "key-sets";
142 private static final String TAG_PERMISSION_GROUP = "permission-group";
143 private static final String TAG_PERMISSION = "permission";
144 private static final String TAG_PERMISSION_TREE = "permission-tree";
145 private static final String TAG_USES_PERMISSION = "uses-permission";
146 private static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
147 private static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23";
148 private static final String TAG_USES_CONFIGURATION = "uses-configuration";
149 private static final String TAG_USES_FEATURE = "uses-feature";
150 private static final String TAG_FEATURE_GROUP = "feature-group";
151 private static final String TAG_USES_SDK = "uses-sdk";
152 private static final String TAG_SUPPORT_SCREENS = "supports-screens";
153 private static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
154 private static final String TAG_INSTRUMENTATION = "instrumentation";
155 private static final String TAG_ORIGINAL_PACKAGE = "original-package";
156 private static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
157 private static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
158 private static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
159 private static final String TAG_SUPPORTS_INPUT = "supports-input";
160 private static final String TAG_EAT_COMMENT = "eat-comment";
161 private static final String TAG_PACKAGE = "package";
Todd Kennedyfdd241a2016-04-28 12:26:53 -0700162 private static final String TAG_RESTRICT_UPDATE = "restrict-update";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800163
164 // These are the tags supported by child packages
165 private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>();
166 static {
167 CHILD_PACKAGE_TAGS.add(TAG_APPLICATION);
168 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION);
169 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_M);
170 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_23);
171 CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION);
172 CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE);
173 CHILD_PACKAGE_TAGS.add(TAG_FEATURE_GROUP);
174 CHILD_PACKAGE_TAGS.add(TAG_USES_SDK);
175 CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS);
176 CHILD_PACKAGE_TAGS.add(TAG_INSTRUMENTATION);
177 CHILD_PACKAGE_TAGS.add(TAG_USES_GL_TEXTURE);
178 CHILD_PACKAGE_TAGS.add(TAG_COMPATIBLE_SCREENS);
179 CHILD_PACKAGE_TAGS.add(TAG_SUPPORTS_INPUT);
180 CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
181 }
182
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700183 /** @hide */
184 public static class NewPermissionInfo {
185 public final String name;
186 public final int sdkVersion;
187 public final int fileVersion;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700188
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700189 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
190 this.name = name;
191 this.sdkVersion = sdkVersion;
192 this.fileVersion = fileVersion;
193 }
194 }
Dianne Hackborn79245122012-03-12 10:51:26 -0700195
196 /** @hide */
197 public static class SplitPermissionInfo {
198 public final String rootPerm;
199 public final String[] newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700200 public final int targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700201
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700202 public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
Dianne Hackborn79245122012-03-12 10:51:26 -0700203 this.rootPerm = rootPerm;
204 this.newPerms = newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700205 this.targetSdk = targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700206 }
207 }
208
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700209 /**
210 * List of new permissions that have been added since 1.0.
211 * NOTE: These must be declared in SDK version order, with permissions
212 * added to older SDKs appearing before those added to newer SDKs.
Dianne Hackborn79245122012-03-12 10:51:26 -0700213 * If sdkVersion is 0, then this is not a permission that we want to
214 * automatically add to older apps, but we do want to allow it to be
215 * granted during a platform update.
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700216 * @hide
217 */
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700218 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
219 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -0700220 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700221 android.os.Build.VERSION_CODES.DONUT, 0),
222 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
223 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700224 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225
Dianne Hackborn79245122012-03-12 10:51:26 -0700226 /**
227 * List of permissions that have been split into more granular or dependent
228 * permissions.
229 * @hide
230 */
231 public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
232 new PackageParser.SplitPermissionInfo[] {
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700233 // READ_EXTERNAL_STORAGE is always required when an app requests
234 // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
235 // write access without read access. The hack here with the target
236 // target SDK version ensures that this grant is always done.
Dianne Hackborn79245122012-03-12 10:51:26 -0700237 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700238 new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700239 android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700240 new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
241 new String[] { android.Manifest.permission.READ_CALL_LOG },
242 android.os.Build.VERSION_CODES.JELLY_BEAN),
243 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
244 new String[] { android.Manifest.permission.WRITE_CALL_LOG },
245 android.os.Build.VERSION_CODES.JELLY_BEAN)
Dianne Hackborn79245122012-03-12 10:51:26 -0700246 };
247
Jeff Sharkey275e0852014-06-17 18:18:49 -0700248 /**
249 * @deprecated callers should move to explicitly passing around source path.
250 */
251 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 private String mArchiveSourcePath;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700255 private boolean mOnlyCoreApps;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700256 private DisplayMetrics mMetrics;
257
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700258 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700259 private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260
261 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
262
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700263 private static boolean sCompatibilityModeEnabled = true;
Amith Yamasani655d0e22013-06-12 14:19:10 -0700264 private static final int PARSE_DEFAULT_INSTALL_LOCATION =
265 PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700266
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700267 static class ParsePackageItemArgs {
268 final Package owner;
269 final String[] outError;
270 final int nameRes;
271 final int labelRes;
272 final int iconRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700273 final int roundIconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700274 final int logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800275 final int bannerRes;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700276
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700277 String tag;
278 TypedArray sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700279
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700280 ParsePackageItemArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700281 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
282 int _bannerRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700283 owner = _owner;
284 outError = _outError;
285 nameRes = _nameRes;
286 labelRes = _labelRes;
287 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700288 logoRes = _logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800289 bannerRes = _bannerRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700290 roundIconRes = _roundIconRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700291 }
292 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700293
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700294 static class ParseComponentArgs extends ParsePackageItemArgs {
295 final String[] sepProcesses;
296 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800297 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700298 final int enabledRes;
299 int flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700300
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700301 ParseComponentArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700302 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
303 int _bannerRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800304 String[] _sepProcesses, int _processRes,
305 int _descriptionRes, int _enabledRes) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700306 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _roundIconRes, _logoRes,
307 _bannerRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700308 sepProcesses = _sepProcesses;
309 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800310 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700311 enabledRes = _enabledRes;
312 }
313 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800314
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700315 /**
Jeff Sharkey73767b92014-07-04 20:18:13 -0700316 * Lightweight parsed details about a single package.
317 */
318 public static class PackageLite {
319 public final String packageName;
320 public final int versionCode;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700321 public final int installLocation;
322 public final VerifierInfo[] verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700323
324 /** Names of any split APKs, ordered by parsed splitName */
325 public final String[] splitNames;
326
327 /**
328 * Path where this package was found on disk. For monolithic packages
329 * this is path to single base APK file; for cluster packages this is
330 * path to the cluster directory.
331 */
332 public final String codePath;
333
334 /** Path of base APK */
335 public final String baseCodePath;
336 /** Paths of any split APKs, ordered by parsed splitName */
337 public final String[] splitCodePaths;
338
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800339 /** Revision code of base APK */
340 public final int baseRevisionCode;
341 /** Revision codes of any split APKs, ordered by parsed splitName */
342 public final int[] splitRevisionCodes;
343
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700344 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100345 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100346 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800347 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700348 public final boolean extractNativeLibs;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100349
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700350 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800351 String[] splitCodePaths, int[] splitRevisionCodes) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700352 this.packageName = baseApk.packageName;
353 this.versionCode = baseApk.versionCode;
354 this.installLocation = baseApk.installLocation;
355 this.verifiers = baseApk.verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700356 this.splitNames = splitNames;
357 this.codePath = codePath;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700358 this.baseCodePath = baseApk.codePath;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700359 this.splitCodePaths = splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800360 this.baseRevisionCode = baseApk.revisionCode;
361 this.splitRevisionCodes = splitRevisionCodes;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700362 this.coreApp = baseApk.coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100363 this.debuggable = baseApk.debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100364 this.multiArch = baseApk.multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800365 this.use32bitAbi = baseApk.use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700366 this.extractNativeLibs = baseApk.extractNativeLibs;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700367 }
368
369 public List<String> getAllCodePaths() {
370 ArrayList<String> paths = new ArrayList<>();
371 paths.add(baseCodePath);
372 if (!ArrayUtils.isEmpty(splitCodePaths)) {
373 Collections.addAll(paths, splitCodePaths);
374 }
375 return paths;
376 }
377 }
378
379 /**
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700380 * Lightweight parsed details about a single APK file.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800381 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700382 public static class ApkLite {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700383 public final String codePath;
Kenny Root05ca4c92011-09-15 10:36:25 -0700384 public final String packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700385 public final String splitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700386 public final int versionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800387 public final int revisionCode;
Kenny Root05ca4c92011-09-15 10:36:25 -0700388 public final int installLocation;
389 public final VerifierInfo[] verifiers;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700390 public final Signature[] signatures;
Todd Kennedyd9d438a2016-04-06 14:08:14 -0700391 public final Certificate[][] certificates;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700392 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100393 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100394 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800395 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700396 public final boolean extractNativeLibs;
Kenny Root05ca4c92011-09-15 10:36:25 -0700397
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700398 public ApkLite(String codePath, String packageName, String splitName, int versionCode,
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800399 int revisionCode, int installLocation, List<VerifierInfo> verifiers,
Todd Kennedyd9d438a2016-04-06 14:08:14 -0700400 Signature[] signatures, Certificate[][] certificates, boolean coreApp,
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100401 boolean debuggable, boolean multiArch, boolean use32bitAbi,
402 boolean extractNativeLibs) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700403 this.codePath = codePath;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800404 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700405 this.splitName = splitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700406 this.versionCode = versionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800407 this.revisionCode = revisionCode;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800408 this.installLocation = installLocation;
Kenny Root05ca4c92011-09-15 10:36:25 -0700409 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700410 this.signatures = signatures;
Todd Kennedyd9d438a2016-04-06 14:08:14 -0700411 this.certificates = certificates;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700412 this.coreApp = coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100413 this.debuggable = debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100414 this.multiArch = multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800415 this.use32bitAbi = use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700416 this.extractNativeLibs = extractNativeLibs;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800417 }
418 }
419
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700420 private ParsePackageItemArgs mParseInstrumentationArgs;
421 private ParseComponentArgs mParseActivityArgs;
422 private ParseComponentArgs mParseActivityAliasArgs;
423 private ParseComponentArgs mParseServiceArgs;
424 private ParseComponentArgs mParseProviderArgs;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 /** If set to true, we will only allow package files that exactly match
427 * the DTD. Otherwise, we try to get as much from the package as we
428 * can without failing. This should normally be set to false, to
429 * support extensions to the DTD in future versions. */
430 private static final boolean RIGID_PARSER = false;
431
432 private static final String TAG = "PackageParser";
433
Jeff Sharkey275e0852014-06-17 18:18:49 -0700434 public PackageParser() {
435 mMetrics = new DisplayMetrics();
436 mMetrics.setToDefaults();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700437 }
438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 public void setSeparateProcesses(String[] procs) {
440 mSeparateProcesses = procs;
441 }
442
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700443 /**
444 * Flag indicating this parser should only consider apps with
445 * {@code coreApp} manifest attribute to be valid apps. This is useful when
446 * creating a minimalist boot environment.
447 */
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700448 public void setOnlyCoreApps(boolean onlyCoreApps) {
449 mOnlyCoreApps = onlyCoreApps;
450 }
451
Jeff Sharkey275e0852014-06-17 18:18:49 -0700452 public void setDisplayMetrics(DisplayMetrics metrics) {
453 mMetrics = metrics;
454 }
455
Jeff Sharkey73767b92014-07-04 20:18:13 -0700456 public static final boolean isApkFile(File file) {
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700457 return isApkPath(file.getName());
458 }
459
460 private static boolean isApkPath(String path) {
461 return path.endsWith(".apk");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800462 }
463
464 /**
465 * Generate and return the {@link PackageInfo} for a parsed package.
466 *
467 * @param p the parsed package.
468 * @param flags indicating which optional information is included.
469 */
470 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Dianne Hackborne639da72012-02-21 15:11:13 -0800471 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svet Ganov3695b8a2015-03-24 16:30:25 -0700472 Set<String> grantedPermissions, PackageUserState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473
Amith Yamasani483f3b02012-03-13 16:08:00 -0700474 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700475 grantedPermissions, state, UserHandle.getCallingUserId());
476 }
477
Amith Yamasani655d0e22013-06-12 14:19:10 -0700478 /**
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700479 * Returns true if the package is installed and not hidden, or if the caller
480 * explicitly wanted all uninstalled and hidden packages as well.
Amith Yamasani655d0e22013-06-12 14:19:10 -0700481 */
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700482 private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state) {
483 return (state.installed && !state.hidden)
Amith Yamasani655d0e22013-06-12 14:19:10 -0700484 || (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700485 }
486
Christopher Tateba629da2013-11-13 17:42:28 -0800487 public static boolean isAvailable(PackageUserState state) {
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700488 return checkUseInstalledOrHidden(0, state);
Christopher Tateba629da2013-11-13 17:42:28 -0800489 }
490
Amith Yamasani13593602012-03-22 16:16:17 -0700491 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Amith Yamasani483f3b02012-03-13 16:08:00 -0700492 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svetoslavc6d1c342015-02-26 14:44:43 -0800493 Set<String> grantedPermissions, PackageUserState state, int userId) {
Jeff Sharkeyc5967e92016-01-07 18:50:29 -0700494 if (!checkUseInstalledOrHidden(flags, state) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700495 return null;
496 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 PackageInfo pi = new PackageInfo();
498 pi.packageName = p.packageName;
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700499 pi.splitNames = p.splitNames;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 pi.versionCode = p.mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800501 pi.baseRevisionCode = p.baseRevisionCode;
502 pi.splitRevisionCodes = p.splitRevisionCodes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 pi.versionName = p.mVersionName;
504 pi.sharedUserId = p.mSharedUserId;
505 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700506 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800507 pi.installLocation = p.installLocation;
Jeff Hao272bf3a2014-10-08 13:34:43 -0700508 pi.coreApp = p.coreApp;
Amith Yamasani0d8750d2013-05-01 15:25:28 -0700509 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
510 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
511 pi.requiredForAllUsers = p.mRequiredForAllUsers;
512 }
Amith Yamasani0ac1fc92013-03-27 18:56:08 -0700513 pi.restrictedAccountType = p.mRestrictedAccountType;
Amith Yamasaniccbe3892013-04-12 17:52:42 -0700514 pi.requiredAccountType = p.mRequiredAccountType;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100515 pi.overlayTarget = p.mOverlayTarget;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700516 pi.firstInstallTime = firstInstallTime;
517 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518 if ((flags&PackageManager.GET_GIDS) != 0) {
519 pi.gids = gids;
520 }
521 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700522 int N = p.configPreferences != null ? p.configPreferences.size() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 if (N > 0) {
524 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700525 p.configPreferences.toArray(pi.configPreferences);
526 }
527 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
528 if (N > 0) {
529 pi.reqFeatures = new FeatureInfo[N];
530 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800531 }
Adam Lesinskid3edfde2014-08-08 17:32:44 -0700532 N = p.featureGroups != null ? p.featureGroups.size() : 0;
533 if (N > 0) {
534 pi.featureGroups = new FeatureGroupInfo[N];
535 p.featureGroups.toArray(pi.featureGroups);
536 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700538 if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
539 final int N = p.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700541 int num = 0;
542 final ActivityInfo[] res = new ActivityInfo[N];
543 for (int i = 0; i < N; i++) {
544 final Activity a = p.activities.get(i);
545 if (state.isMatch(a.info, flags)) {
546 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800547 }
548 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700549 pi.activities = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 }
551 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700552 if ((flags & PackageManager.GET_RECEIVERS) != 0) {
553 final int N = p.receivers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700555 int num = 0;
556 final ActivityInfo[] res = new ActivityInfo[N];
557 for (int i = 0; i < N; i++) {
558 final Activity a = p.receivers.get(i);
559 if (state.isMatch(a.info, flags)) {
560 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800561 }
562 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700563 pi.receivers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800564 }
565 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700566 if ((flags & PackageManager.GET_SERVICES) != 0) {
567 final int N = p.services.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800568 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700569 int num = 0;
570 final ServiceInfo[] res = new ServiceInfo[N];
571 for (int i = 0; i < N; i++) {
572 final Service s = p.services.get(i);
573 if (state.isMatch(s.info, flags)) {
574 res[num++] = generateServiceInfo(s, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800575 }
576 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700577 pi.services = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800578 }
579 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700580 if ((flags & PackageManager.GET_PROVIDERS) != 0) {
581 final int N = p.providers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700583 int num = 0;
584 final ProviderInfo[] res = new ProviderInfo[N];
585 for (int i = 0; i < N; i++) {
586 final Provider pr = p.providers.get(i);
587 if (state.isMatch(pr.info, flags)) {
588 res[num++] = generateProviderInfo(pr, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589 }
590 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700591 pi.providers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800592 }
593 }
594 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
595 int N = p.instrumentation.size();
596 if (N > 0) {
597 pi.instrumentation = new InstrumentationInfo[N];
598 for (int i=0; i<N; i++) {
599 pi.instrumentation[i] = generateInstrumentationInfo(
600 p.instrumentation.get(i), flags);
601 }
602 }
603 }
604 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
605 int N = p.permissions.size();
606 if (N > 0) {
607 pi.permissions = new PermissionInfo[N];
608 for (int i=0; i<N; i++) {
609 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
610 }
611 }
612 N = p.requestedPermissions.size();
613 if (N > 0) {
614 pi.requestedPermissions = new String[N];
Dianne Hackborne639da72012-02-21 15:11:13 -0800615 pi.requestedPermissionsFlags = new int[N];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 for (int i=0; i<N; i++) {
Dianne Hackborne639da72012-02-21 15:11:13 -0800617 final String perm = p.requestedPermissions.get(i);
618 pi.requestedPermissions[i] = perm;
Svet Ganov3695b8a2015-03-24 16:30:25 -0700619 // The notion of required permissions is deprecated but for compatibility.
Svetoslavc6d1c342015-02-26 14:44:43 -0800620 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800621 if (grantedPermissions != null && grantedPermissions.contains(perm)) {
622 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
623 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624 }
625 }
626 }
627 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700628 int N = (p.mSignatures != null) ? p.mSignatures.length : 0;
629 if (N > 0) {
630 pi.signatures = new Signature[N];
631 System.arraycopy(p.mSignatures, 0, pi.signatures, 0, N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632 }
633 }
634 return pi;
635 }
636
Jeff Sharkey275e0852014-06-17 18:18:49 -0700637 private static Certificate[][] loadCertificates(StrictJarFile jarFile, ZipEntry entry)
638 throws PackageParserException {
639 InputStream is = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800640 try {
641 // We must read the stream for the JarEntry to retrieve
642 // its certificates.
Jeff Sharkey275e0852014-06-17 18:18:49 -0700643 is = jarFile.getInputStream(entry);
644 readFullyIgnoringContents(is);
645 return jarFile.getCertificateChains(entry);
646 } catch (IOException | RuntimeException e) {
647 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
648 "Failed reading " + entry.getName() + " in " + jarFile, e);
649 } finally {
650 IoUtils.closeQuietly(is);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800651 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652 }
653
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800654 public final static int PARSE_IS_SYSTEM = 1<<0;
655 public final static int PARSE_CHATTY = 1<<1;
656 public final static int PARSE_MUST_BE_APK = 1<<2;
657 public final static int PARSE_IGNORE_PROCESSES = 1<<3;
658 public final static int PARSE_FORWARD_LOCK = 1<<4;
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -0700659 public final static int PARSE_EXTERNAL_STORAGE = 1<<5;
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700660 public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
Christopher Tateccbf84f2013-05-08 15:25:41 -0700661 public final static int PARSE_IS_PRIVILEGED = 1<<7;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700662 public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700663 public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
Christopher Tatef3d939c2015-09-17 12:25:51 -0700664 public final static int PARSE_ENFORCE_CODE = 1<<10;
Todd Kennedy373f0b42015-12-16 14:45:14 -0800665 public final static int PARSE_IS_EPHEMERAL = 1<<11;
Todd Kennedyb1072712016-04-26 15:41:20 -0700666 public final static int PARSE_FORCE_SDK = 1<<12;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700667
668 private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700670 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700671 * Used to sort a set of APKs based on their split names, always placing the
672 * base APK (with {@code null} split name) first.
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700673 */
Jeff Sharkey275e0852014-06-17 18:18:49 -0700674 private static class SplitNameComparator implements Comparator<String> {
675 @Override
676 public int compare(String lhs, String rhs) {
677 if (lhs == null) {
678 return -1;
679 } else if (rhs == null) {
680 return 1;
681 } else {
682 return lhs.compareTo(rhs);
683 }
684 }
685 }
686
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700687 /**
688 * Parse only lightweight details about the package at the given location.
689 * Automatically detects if the package is a monolithic style (single APK
690 * file) or cluster style (directory of APKs).
691 * <p>
692 * This performs sanity checking on cluster style packages, such as
693 * requiring identical package name and version codes, a single base APK,
694 * and unique split names.
695 *
696 * @see PackageParser#parsePackage(File, int)
697 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700698 public static PackageLite parsePackageLite(File packageFile, int flags)
699 throws PackageParserException {
700 if (packageFile.isDirectory()) {
701 return parseClusterPackageLite(packageFile, flags);
702 } else {
703 return parseMonolithicPackageLite(packageFile, flags);
704 }
705 }
706
707 private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
708 throws PackageParserException {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700709 final ApkLite baseApk = parseApkLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700710 final String packagePath = packageFile.getAbsolutePath();
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800711 return new PackageLite(packagePath, baseApk, null, null, null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700712 }
713
714 private static PackageLite parseClusterPackageLite(File packageDir, int flags)
715 throws PackageParserException {
716 final File[] files = packageDir.listFiles();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700717 if (ArrayUtils.isEmpty(files)) {
718 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
719 "No packages found in split");
720 }
721
Jeff Sharkey275e0852014-06-17 18:18:49 -0700722 String packageName = null;
723 int versionCode = 0;
724
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700725 final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700726 for (File file : files) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700727 if (isApkFile(file)) {
728 final ApkLite lite = parseApkLite(file, flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -0700729
730 // Assert that all package names and version codes are
731 // consistent with the first one we encounter.
732 if (packageName == null) {
733 packageName = lite.packageName;
734 versionCode = lite.versionCode;
735 } else {
736 if (!packageName.equals(lite.packageName)) {
737 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
738 "Inconsistent package " + lite.packageName + " in " + file
739 + "; expected " + packageName);
740 }
741 if (versionCode != lite.versionCode) {
742 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
743 "Inconsistent version " + lite.versionCode + " in " + file
744 + "; expected " + versionCode);
745 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700746 }
747
Jeff Sharkey275e0852014-06-17 18:18:49 -0700748 // Assert that each split is defined only once
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700749 if (apks.put(lite.splitName, lite) != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700750 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
751 "Split name " + lite.splitName
752 + " defined more than once; most recent was " + file);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700753 }
754 }
755 }
756
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700757 final ApkLite baseApk = apks.remove(null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700758 if (baseApk == null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700759 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
Jeff Sharkey73767b92014-07-04 20:18:13 -0700760 "Missing base APK in " + packageDir);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700761 }
762
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700763 // Always apply deterministic ordering based on splitName
764 final int size = apks.size();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700765
Jeff Sharkey73767b92014-07-04 20:18:13 -0700766 String[] splitNames = null;
767 String[] splitCodePaths = null;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800768 int[] splitRevisionCodes = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700769 if (size > 0) {
770 splitNames = new String[size];
771 splitCodePaths = new String[size];
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800772 splitRevisionCodes = new int[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700773
774 splitNames = apks.keySet().toArray(splitNames);
775 Arrays.sort(splitNames, sSplitNameComparator);
776
777 for (int i = 0; i < size; i++) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700778 splitCodePaths[i] = apks.get(splitNames[i]).codePath;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800779 splitRevisionCodes[i] = apks.get(splitNames[i]).revisionCode;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700780 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700781 }
782
Jeff Sharkey73767b92014-07-04 20:18:13 -0700783 final String codePath = packageDir.getAbsolutePath();
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800784 return new PackageLite(codePath, baseApk, splitNames, splitCodePaths,
785 splitRevisionCodes);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700786 }
787
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700788 /**
789 * Parse the package at the given location. Automatically detects if the
790 * package is a monolithic style (single APK file) or cluster style
791 * (directory of APKs).
792 * <p>
793 * This performs sanity checking on cluster style packages, such as
794 * requiring identical package name and version codes, a single base APK,
795 * and unique split names.
796 * <p>
797 * Note that this <em>does not</em> perform signature verification; that
798 * must be done separately in {@link #collectCertificates(Package, int)}.
799 *
800 * @see #parsePackageLite(File, int)
801 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700802 public Package parsePackage(File packageFile, int flags) throws PackageParserException {
803 if (packageFile.isDirectory()) {
804 return parseClusterPackage(packageFile, flags);
805 } else {
806 return parseMonolithicPackage(packageFile, flags);
807 }
808 }
809
810 /**
811 * Parse all APKs contained in the given directory, treating them as a
812 * single package. This also performs sanity checking, such as requiring
813 * identical package name and version codes, a single base APK, and unique
814 * split names.
815 * <p>
816 * Note that this <em>does not</em> perform signature verification; that
817 * must be done separately in {@link #collectCertificates(Package, int)}.
818 */
819 private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
820 final PackageLite lite = parseClusterPackageLite(packageDir, 0);
821
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700822 if (mOnlyCoreApps && !lite.coreApp) {
823 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
824 "Not a coreApp: " + packageDir);
825 }
826
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700827 final AssetManager assets = new AssetManager();
828 try {
829 // Load the base and all splits into the AssetManager
830 // so that resources can be overriden when parsing the manifests.
831 loadApkIntoAssetManager(assets, lite.baseCodePath, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700832
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700833 if (!ArrayUtils.isEmpty(lite.splitCodePaths)) {
834 for (String path : lite.splitCodePaths) {
835 loadApkIntoAssetManager(assets, path, flags);
836 }
Jeff Sharkey73767b92014-07-04 20:18:13 -0700837 }
Jeff Sharkey73767b92014-07-04 20:18:13 -0700838
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700839 final File baseApk = new File(lite.baseCodePath);
840 final Package pkg = parseBaseApk(baseApk, assets, flags);
841 if (pkg == null) {
842 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
843 "Failed to parse base APK: " + baseApk);
844 }
845
846 if (!ArrayUtils.isEmpty(lite.splitNames)) {
847 final int num = lite.splitNames.length;
848 pkg.splitNames = lite.splitNames;
849 pkg.splitCodePaths = lite.splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800850 pkg.splitRevisionCodes = lite.splitRevisionCodes;
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700851 pkg.splitFlags = new int[num];
Alex Klyubinb9f8a522015-02-03 11:12:59 -0800852 pkg.splitPrivateFlags = new int[num];
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700853
854 for (int i = 0; i < num; i++) {
855 parseSplitApk(pkg, i, assets, flags);
856 }
857 }
858
Svet Ganov354cd3c2015-12-17 11:35:04 -0800859 pkg.setCodePath(packageDir.getAbsolutePath());
Selim Gurun2d291d82016-02-05 17:50:53 -0800860 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700861 return pkg;
862 } finally {
863 IoUtils.closeQuietly(assets);
864 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 }
866
Jeff Sharkey275e0852014-06-17 18:18:49 -0700867 /**
868 * Parse the given APK file, treating it as as a single monolithic package.
869 * <p>
870 * Note that this <em>does not</em> perform signature verification; that
871 * must be done separately in {@link #collectCertificates(Package, int)}.
Jeff Sharkeyd7460572014-07-06 20:44:55 -0700872 *
873 * @deprecated external callers should move to
874 * {@link #parsePackage(File, int)}. Eventually this method will
875 * be marked private.
Jeff Sharkey275e0852014-06-17 18:18:49 -0700876 */
Jeff Sharkeyd7460572014-07-06 20:44:55 -0700877 @Deprecated
Jeff Sharkey275e0852014-06-17 18:18:49 -0700878 public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
Tao Baic9a02372016-01-12 15:02:24 -0800879 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700880 if (mOnlyCoreApps) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700881 if (!lite.coreApp) {
882 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
883 "Not a coreApp: " + apkFile);
884 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700885 }
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700886
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700887 final AssetManager assets = new AssetManager();
888 try {
889 final Package pkg = parseBaseApk(apkFile, assets, flags);
Svet Ganov354cd3c2015-12-17 11:35:04 -0800890 pkg.setCodePath(apkFile.getAbsolutePath());
Selim Gurun2d291d82016-02-05 17:50:53 -0800891 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700892 return pkg;
893 } finally {
894 IoUtils.closeQuietly(assets);
895 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700896 }
897
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700898 private static int loadApkIntoAssetManager(AssetManager assets, String apkPath, int flags)
899 throws PackageParserException {
900 if ((flags & PARSE_MUST_BE_APK) != 0 && !isApkPath(apkPath)) {
901 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
902 "Invalid package file: " + apkPath);
903 }
904
905 // The AssetManager guarantees uniqueness for asset paths, so if this asset path
906 // already exists in the AssetManager, addAssetPath will only return the cookie
907 // assigned to it.
908 int cookie = assets.addAssetPath(apkPath);
909 if (cookie == 0) {
910 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
911 "Failed adding asset path: " + apkPath);
912 }
913 return cookie;
914 }
915
916 private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
917 throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700918 final String apkPath = apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -0700919
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700920 String volumeUuid = null;
921 if (apkPath.startsWith(MNT_EXPAND)) {
922 final int end = apkPath.indexOf('/', MNT_EXPAND.length());
923 volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
924 }
925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 mParseError = PackageManager.INSTALL_SUCCEEDED;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700927 mArchiveSourcePath = apkFile.getAbsolutePath();
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700928
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700929 if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700931 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
932
Dianne Hackborn3b81bc12011-01-15 11:50:52 -0800933 Resources res = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700934 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700936 res = new Resources(assets, mMetrics, null);
937 assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
938 Build.VERSION.RESOURCES_SDK_INT);
939 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
940
941 final String[] outError = new String[1];
942 final Package pkg = parseBaseApk(res, parser, flags, outError);
943 if (pkg == null) {
944 throw new PackageParserException(mParseError,
945 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700947
Svet Ganov354cd3c2015-12-17 11:35:04 -0800948 pkg.setVolumeUuid(volumeUuid);
949 pkg.setApplicationVolumeUuid(volumeUuid);
950 pkg.setBaseCodePath(apkPath);
951 pkg.setSignatures(null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700952
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700953 return pkg;
954
955 } catch (PackageParserException e) {
956 throw e;
957 } catch (Exception e) {
958 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -0700959 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700960 } finally {
961 IoUtils.closeQuietly(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800963 }
964
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700965 private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700966 throws PackageParserException {
967 final String apkPath = pkg.splitCodePaths[splitIndex];
Jeff Sharkey275e0852014-06-17 18:18:49 -0700968
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700969 mParseError = PackageManager.INSTALL_SUCCEEDED;
970 mArchiveSourcePath = apkPath;
971
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700972 if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
973
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700974 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
975
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700976 Resources res = null;
977 XmlResourceParser parser = null;
978 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700979 res = new Resources(assets, mMetrics, null);
980 assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
981 Build.VERSION.RESOURCES_SDK_INT);
982 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
983
984 final String[] outError = new String[1];
985 pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
986 if (pkg == null) {
987 throw new PackageParserException(mParseError,
988 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
989 }
990
991 } catch (PackageParserException e) {
992 throw e;
993 } catch (Exception e) {
994 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -0700995 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700996 } finally {
997 IoUtils.closeQuietly(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700998 }
999 }
1000
1001 /**
1002 * Parse the manifest of a <em>split APK</em>.
1003 * <p>
1004 * Note that split APKs have many more restrictions on what they're capable
1005 * of doing, so many valid features of a base APK have been carefully
1006 * omitted here.
1007 */
1008 private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001009 int splitIndex, String[] outError) throws XmlPullParserException, IOException,
1010 PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001011 AttributeSet attrs = parser;
1012
Jeff Sharkey78a13012014-07-15 20:18:34 -07001013 // We parsed manifest tag earlier; just skip past it
Svet Ganov354cd3c2015-12-17 11:35:04 -08001014 parsePackageSplitNames(parser, attrs);
Jeff Sharkey78a13012014-07-15 20:18:34 -07001015
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001016 mParseInstrumentationArgs = null;
1017 mParseActivityArgs = null;
1018 mParseServiceArgs = null;
1019 mParseProviderArgs = null;
1020
1021 int type;
1022
1023 boolean foundApp = false;
1024
1025 int outerDepth = parser.getDepth();
1026 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1027 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1028 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1029 continue;
1030 }
1031
1032 String tagName = parser.getName();
1033 if (tagName.equals("application")) {
1034 if (foundApp) {
1035 if (RIGID_PARSER) {
1036 outError[0] = "<manifest> has more than one <application>";
1037 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1038 return null;
1039 } else {
1040 Slog.w(TAG, "<manifest> has more than one <application>");
1041 XmlUtils.skipCurrentTag(parser);
1042 continue;
1043 }
1044 }
1045
1046 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001047 if (!parseSplitApplication(pkg, res, parser, flags, splitIndex, outError)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001048 return null;
1049 }
1050
1051 } else if (RIGID_PARSER) {
1052 outError[0] = "Bad element under <manifest>: "
1053 + parser.getName();
1054 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1055 return null;
1056
1057 } else {
1058 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1059 + " at " + mArchiveSourcePath + " "
1060 + parser.getPositionDescription());
1061 XmlUtils.skipCurrentTag(parser);
1062 continue;
1063 }
1064 }
1065
1066 if (!foundApp) {
1067 outError[0] = "<manifest> does not contain an <application>";
1068 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1069 }
1070
1071 return pkg;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001072 }
1073
Todd Kennedy66c55532016-02-26 16:22:11 -08001074 public static int getApkSigningVersion(Package pkg) {
1075 try {
1076 if (ApkSignatureSchemeV2Verifier.hasSignature(pkg.baseCodePath)) {
1077 return APK_SIGNING_V2;
1078 }
1079 return APK_SIGNING_V1;
1080 } catch (IOException e) {
1081 }
1082 return APK_SIGNING_UNKNOWN;
1083 }
1084
Kenny Root6c918ce2013-04-02 14:04:24 -07001085 /**
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001086 * Populates the correct packages fields with the given certificates.
1087 * <p>
1088 * This is useful when we've already processed the certificates [such as during package
1089 * installation through an installer session]. We don't re-process the archive and
1090 * simply populate the correct fields.
1091 */
1092 public static void populateCertificates(Package pkg, Certificate[][] certificates)
1093 throws PackageParserException {
1094 pkg.mCertificates = null;
1095 pkg.mSignatures = null;
1096 pkg.mSigningKeys = null;
1097
1098 pkg.mCertificates = certificates;
1099 try {
1100 pkg.mSignatures = convertToSignatures(certificates);
1101 } catch (CertificateEncodingException e) {
1102 // certificates weren't encoded properly; something went wrong
1103 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1104 "Failed to collect certificates from " + pkg.baseCodePath, e);
1105 }
1106 pkg.mSigningKeys = new ArraySet<>(certificates.length);
1107 for (int i = 0; i < certificates.length; i++) {
1108 Certificate[] signerCerts = certificates[i];
1109 Certificate signerCert = signerCerts[0];
1110 pkg.mSigningKeys.add(signerCert.getPublicKey());
1111 }
1112 // add signatures to child packages
1113 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1114 for (int i = 0; i < childCount; i++) {
1115 Package childPkg = pkg.childPackages.get(i);
1116 childPkg.mCertificates = pkg.mCertificates;
1117 childPkg.mSignatures = pkg.mSignatures;
1118 childPkg.mSigningKeys = pkg.mSigningKeys;
1119 }
1120 }
1121
1122 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -07001123 * Collect certificates from all the APKs described in the given package,
Todd Kennedy373f0b42015-12-16 14:45:14 -08001124 * populating {@link Package#mSignatures}. Also asserts that all APK
Jeff Sharkey275e0852014-06-17 18:18:49 -07001125 * contents are signed correctly and consistently.
1126 */
Todd Kennedy66c55532016-02-26 16:22:11 -08001127 public static void collectCertificates(Package pkg, int parseFlags)
1128 throws PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001129 collectCertificatesInternal(pkg, parseFlags);
1130 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1131 for (int i = 0; i < childCount; i++) {
1132 Package childPkg = pkg.childPackages.get(i);
1133 childPkg.mCertificates = pkg.mCertificates;
1134 childPkg.mSignatures = pkg.mSignatures;
1135 childPkg.mSigningKeys = pkg.mSigningKeys;
1136 }
1137 }
1138
Todd Kennedy66c55532016-02-26 16:22:11 -08001139 private static void collectCertificatesInternal(Package pkg, int parseFlags)
1140 throws PackageParserException {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001141 pkg.mCertificates = null;
1142 pkg.mSignatures = null;
1143 pkg.mSigningKeys = null;
1144
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001145 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1146 try {
Todd Kennedyf720a9d2016-04-15 09:44:36 -07001147 collectCertificates(pkg, new File(pkg.baseCodePath), parseFlags);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001148
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001149 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
1150 for (int i = 0; i < pkg.splitCodePaths.length; i++) {
Todd Kennedyf720a9d2016-04-15 09:44:36 -07001151 collectCertificates(pkg, new File(pkg.splitCodePaths[i]), parseFlags);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001152 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001153 }
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001154 } finally {
1155 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001156 }
1157 }
1158
Todd Kennedyf720a9d2016-04-15 09:44:36 -07001159 private static void collectCertificates(Package pkg, File apkFile, int parseFlags)
Jeff Sharkey275e0852014-06-17 18:18:49 -07001160 throws PackageParserException {
1161 final String apkPath = apkFile.getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162
Alex Klyubine4157182016-01-05 13:27:05 -08001163 // Try to verify the APK using APK Signature Scheme v2.
1164 boolean verified = false;
1165 {
1166 Certificate[][] allSignersCerts = null;
1167 Signature[] signatures = null;
1168 try {
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001169 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV2");
Alex Klyubine4157182016-01-05 13:27:05 -08001170 allSignersCerts = ApkSignatureSchemeV2Verifier.verify(apkPath);
1171 signatures = convertToSignatures(allSignersCerts);
1172 // APK verified using APK Signature Scheme v2.
1173 verified = true;
1174 } catch (ApkSignatureSchemeV2Verifier.SignatureNotFoundException e) {
1175 // No APK Signature Scheme v2 signature found
1176 } catch (Exception e) {
1177 // APK Signature Scheme v2 signature was found but did not verify
1178 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1179 "Failed to collect certificates from " + apkPath
1180 + " using APK Signature Scheme v2",
1181 e);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001182 } finally {
1183 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Alex Klyubine4157182016-01-05 13:27:05 -08001184 }
1185
1186 if (verified) {
1187 if (pkg.mCertificates == null) {
1188 pkg.mCertificates = allSignersCerts;
1189 pkg.mSignatures = signatures;
1190 pkg.mSigningKeys = new ArraySet<>(allSignersCerts.length);
1191 for (int i = 0; i < allSignersCerts.length; i++) {
1192 Certificate[] signerCerts = allSignersCerts[i];
1193 Certificate signerCert = signerCerts[0];
1194 pkg.mSigningKeys.add(signerCert.getPublicKey());
1195 }
1196 } else {
1197 if (!Signature.areExactMatch(pkg.mSignatures, signatures)) {
1198 throw new PackageParserException(
1199 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
1200 apkPath + " has mismatched certificates");
1201 }
1202 }
1203 // Not yet done, because we need to confirm that AndroidManifest.xml exists and,
1204 // if requested, that classes.dex exists.
1205 }
1206 }
1207
Jeff Sharkey275e0852014-06-17 18:18:49 -07001208 StrictJarFile jarFile = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001209 try {
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001210 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor");
Alex Klyubin9b59bc42016-03-24 12:02:20 -07001211 // Ignore signature stripping protections when verifying APKs from system partition.
1212 // For those APKs we only care about extracting signer certificates, and don't care
1213 // about verifying integrity.
1214 boolean signatureSchemeRollbackProtectionsEnforced =
Todd Kennedyd022ac22016-04-13 10:49:29 -07001215 (parseFlags & PARSE_IS_SYSTEM_DIR) == 0;
Alex Klyubine4157182016-01-05 13:27:05 -08001216 jarFile = new StrictJarFile(
1217 apkPath,
Alex Klyubin9b59bc42016-03-24 12:02:20 -07001218 !verified, // whether to verify JAR signature
1219 signatureSchemeRollbackProtectionsEnforced);
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001220 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001221
Jeff Sharkey275e0852014-06-17 18:18:49 -07001222 // Always verify manifest, regardless of source
1223 final ZipEntry manifestEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
1224 if (manifestEntry == null) {
1225 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1226 "Package " + apkPath + " has no manifest");
1227 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001228
Alex Klyubine4157182016-01-05 13:27:05 -08001229 // Optimization: early termination when APK already verified
1230 if (verified) {
Alex Klyubine4157182016-01-05 13:27:05 -08001231 return;
1232 }
1233
1234 // APK's integrity needs to be verified using JAR signature scheme.
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001235 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV1");
Jeff Sharkey275e0852014-06-17 18:18:49 -07001236 final List<ZipEntry> toVerify = new ArrayList<>();
1237 toVerify.add(manifestEntry);
1238
1239 // If we're parsing an untrusted package, verify all contents
Todd Kennedyd022ac22016-04-13 10:49:29 -07001240 if ((parseFlags & PARSE_IS_SYSTEM_DIR) == 0) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001241 final Iterator<ZipEntry> i = jarFile.iterator();
1242 while (i.hasNext()) {
1243 final ZipEntry entry = i.next();
1244
1245 if (entry.isDirectory()) continue;
Christopher Tatef3d939c2015-09-17 12:25:51 -07001246
1247 final String entryName = entry.getName();
1248 if (entryName.startsWith("META-INF/")) continue;
1249 if (entryName.equals(ANDROID_MANIFEST_FILENAME)) continue;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001250
1251 toVerify.add(entry);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001252 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001253 }
1254
1255 // Verify that entries are signed consistently with the first entry
1256 // we encountered. Note that for splits, certificates may have
1257 // already been populated during an earlier parse of a base APK.
1258 for (ZipEntry entry : toVerify) {
1259 final Certificate[][] entryCerts = loadCertificates(jarFile, entry);
1260 if (ArrayUtils.isEmpty(entryCerts)) {
1261 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1262 "Package " + apkPath + " has no certificates at entry "
1263 + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001264 }
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001265 final Signature[] entrySignatures = convertToSignatures(entryCerts);
Kenny Rootd2d29252011-08-08 11:27:57 -07001266
Jeff Sharkey275e0852014-06-17 18:18:49 -07001267 if (pkg.mCertificates == null) {
1268 pkg.mCertificates = entryCerts;
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001269 pkg.mSignatures = entrySignatures;
dcashman55b10782014-04-09 14:20:38 -07001270 pkg.mSigningKeys = new ArraySet<PublicKey>();
1271 for (int i=0; i < entryCerts.length; i++) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001272 pkg.mSigningKeys.add(entryCerts[i][0].getPublicKey());
Kenny Rootbcc954d2011-08-08 16:19:08 -07001273 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001274 } else {
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001275 if (!Signature.areExactMatch(pkg.mSignatures, entrySignatures)) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001276 throw new PackageParserException(
1277 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, "Package " + apkPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001278 + " has mismatched certificates at entry "
Jeff Sharkey275e0852014-06-17 18:18:49 -07001279 + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001280 }
1281 }
1282 }
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001283 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeybc097552014-09-09 14:57:26 -07001284 } catch (GeneralSecurityException e) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001285 throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING,
1286 "Failed to collect certificates from " + apkPath, e);
Jeff Sharkeybc097552014-09-09 14:57:26 -07001287 } catch (IOException | RuntimeException e) {
1288 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1289 "Failed to collect certificates from " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001290 } finally {
1291 closeQuietly(jarFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001292 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001293 }
1294
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001295 private static Signature[] convertToSignatures(Certificate[][] certs)
1296 throws CertificateEncodingException {
1297 final Signature[] res = new Signature[certs.length];
1298 for (int i = 0; i < certs.length; i++) {
1299 res[i] = new Signature(certs[i]);
1300 }
1301 return res;
1302 }
1303
Jeff Sharkey275e0852014-06-17 18:18:49 -07001304 /**
1305 * Utility method that retrieves lightweight details about a single APK
1306 * file, including package name, split name, and install location.
1307 *
1308 * @param apkFile path to a single APK
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001309 * @param flags optional parse flags, such as
1310 * {@link #PARSE_COLLECT_CERTIFICATES}
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001311 */
Jeff Sharkey275e0852014-06-17 18:18:49 -07001312 public static ApkLite parseApkLite(File apkFile, int flags)
1313 throws PackageParserException {
1314 final String apkPath = apkFile.getAbsolutePath();
1315
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001316 AssetManager assets = null;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001317 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001318 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001319 assets = new AssetManager();
1320 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 -08001321 Build.VERSION.RESOURCES_SDK_INT);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001322
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001323 int cookie = assets.addAssetPath(apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001324 if (cookie == 0) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001325 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1326 "Failed to parse " + apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001327 }
1328
Kenny Root05ca4c92011-09-15 10:36:25 -07001329 final DisplayMetrics metrics = new DisplayMetrics();
1330 metrics.setToDefaults();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001331
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001332 final Resources res = new Resources(assets, metrics, null);
1333 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Kenny Root05ca4c92011-09-15 10:36:25 -07001334
Jeff Sharkey275e0852014-06-17 18:18:49 -07001335 final Signature[] signatures;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001336 final Certificate[][] certificates;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001337 if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
1338 // TODO: factor signature related items out of Package object
1339 final Package tempPkg = new Package(null);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001340 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1341 try {
Todd Kennedyf720a9d2016-04-15 09:44:36 -07001342 collectCertificates(tempPkg, apkFile, 0 /*parseFlags*/);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001343 } finally {
1344 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1345 }
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001346 signatures = tempPkg.mSignatures;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001347 certificates = tempPkg.mCertificates;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001348 } else {
1349 signatures = null;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001350 certificates = null;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001351 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001352
Jeff Sharkey275e0852014-06-17 18:18:49 -07001353 final AttributeSet attrs = parser;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001354 return parseApkLite(apkPath, res, parser, attrs, flags, signatures, certificates);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001355
1356 } catch (XmlPullParserException | IOException | RuntimeException e) {
1357 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1358 "Failed to parse " + apkPath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001359 } finally {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001360 IoUtils.closeQuietly(parser);
1361 IoUtils.closeQuietly(assets);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363 }
1364
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001365 private static String validateName(String name, boolean requireSeparator,
1366 boolean requireFilename) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001367 final int N = name.length();
1368 boolean hasSep = false;
1369 boolean front = true;
1370 for (int i=0; i<N; i++) {
1371 final char c = name.charAt(i);
1372 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1373 front = false;
1374 continue;
1375 }
1376 if (!front) {
1377 if ((c >= '0' && c <= '9') || c == '_') {
1378 continue;
1379 }
1380 }
1381 if (c == '.') {
1382 hasSep = true;
1383 front = true;
1384 continue;
1385 }
1386 return "bad character '" + c + "'";
1387 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001388 if (requireFilename && !FileUtils.isValidExtFilename(name)) {
1389 return "Invalid filename";
1390 }
1391 return hasSep || !requireSeparator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 ? null : "must have at least one '.' separator";
1393 }
1394
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001395 private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
Svet Ganov354cd3c2015-12-17 11:35:04 -08001396 AttributeSet attrs) throws IOException, XmlPullParserException,
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001397 PackageParserException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001398
1399 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001400 while ((type = parser.next()) != XmlPullParser.START_TAG
1401 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 }
1403
Kenny Rootd2d29252011-08-08 11:27:57 -07001404 if (type != XmlPullParser.START_TAG) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001405 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1406 "No start tag found");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001408 if (!parser.getName().equals(TAG_MANIFEST)) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001409 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1410 "No <manifest> tag");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001411 }
1412
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001413 final String packageName = attrs.getAttributeValue(null, "package");
1414 if (!"android".equals(packageName)) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001415 final String error = validateName(packageName, true, true);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001416 if (error != null) {
1417 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1418 "Invalid manifest package: " + error);
1419 }
1420 }
1421
Jeff Sharkey275e0852014-06-17 18:18:49 -07001422 String splitName = attrs.getAttributeValue(null, "split");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001423 if (splitName != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001424 if (splitName.length() == 0) {
1425 splitName = null;
1426 } else {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001427 final String error = validateName(splitName, false, false);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001428 if (error != null) {
1429 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1430 "Invalid manifest split: " + error);
1431 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001432 }
1433 }
1434
1435 return Pair.create(packageName.intern(),
1436 (splitName != null) ? splitName.intern() : splitName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437 }
1438
Jeff Sharkeybe520fb2014-07-04 18:23:17 -07001439 private static ApkLite parseApkLite(String codePath, Resources res, XmlPullParser parser,
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001440 AttributeSet attrs, int flags, Signature[] signatures, Certificate[][] certificates)
1441 throws IOException, XmlPullParserException, PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001442 final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001443
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001444 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001445 int versionCode = 0;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001446 int revisionCode = 0;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001447 boolean coreApp = false;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001448 boolean debuggable = false;
Narayan Kamathff110bd2014-07-04 18:30:45 +01001449 boolean multiArch = false;
Selim Gurun2d291d82016-02-05 17:50:53 -08001450 boolean use32bitAbi = false;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001451 boolean extractNativeLibs = true;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001452
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001453 for (int i = 0; i < attrs.getAttributeCount(); i++) {
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001454 final String attr = attrs.getAttributeName(i);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001455 if (attr.equals("installLocation")) {
1456 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001457 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001458 } else if (attr.equals("versionCode")) {
1459 versionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001460 } else if (attr.equals("revisionCode")) {
1461 revisionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001462 } else if (attr.equals("coreApp")) {
1463 coreApp = attrs.getAttributeBooleanValue(i, false);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001464 }
1465 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001466
1467 // Only search the tree when the tag is directly below <manifest>
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001468 int type;
Kenny Root05ca4c92011-09-15 10:36:25 -07001469 final int searchDepth = parser.getDepth() + 1;
1470
1471 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
1472 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1473 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
1474 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1475 continue;
1476 }
1477
1478 if (parser.getDepth() == searchDepth && "package-verifier".equals(parser.getName())) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001479 final VerifierInfo verifier = parseVerifier(res, parser, attrs, flags);
Kenny Root05ca4c92011-09-15 10:36:25 -07001480 if (verifier != null) {
1481 verifiers.add(verifier);
1482 }
1483 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001484
1485 if (parser.getDepth() == searchDepth && "application".equals(parser.getName())) {
1486 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1487 final String attr = attrs.getAttributeName(i);
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001488 if ("debuggable".equals(attr)) {
1489 debuggable = attrs.getAttributeBooleanValue(i, false);
1490 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001491 if ("multiArch".equals(attr)) {
1492 multiArch = attrs.getAttributeBooleanValue(i, false);
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001493 }
Selim Gurun2d291d82016-02-05 17:50:53 -08001494 if ("use32bitAbi".equals(attr)) {
1495 use32bitAbi = attrs.getAttributeBooleanValue(i, false);
Tao Baic9a02372016-01-12 15:02:24 -08001496 }
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001497 if ("extractNativeLibs".equals(attr)) {
1498 extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
Narayan Kamatha8755a82014-07-15 12:26:35 +01001499 }
1500 }
1501 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001502 }
1503
Jeff Sharkeybe520fb2014-07-04 18:23:17 -07001504 return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode,
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001505 revisionCode, installLocation, verifiers, signatures, certificates, coreApp,
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001506 debuggable, multiArch, use32bitAbi, extractNativeLibs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001507 }
1508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 /**
1510 * Temporary.
1511 */
1512 static public Signature stringToSignature(String str) {
1513 final int N = str.length();
1514 byte[] sig = new byte[N];
1515 for (int i=0; i<N; i++) {
1516 sig[i] = (byte)str.charAt(i);
1517 }
1518 return new Signature(sig);
1519 }
1520
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001521 /**
Svet Ganov354cd3c2015-12-17 11:35:04 -08001522 * Parses a child package and adds it to the parent if successful. If you add
1523 * new tags that need to be supported by child packages make sure to add them
1524 * to {@link #CHILD_PACKAGE_TAGS}.
1525 *
1526 * @param parentPkg The parent that contains the child
1527 * @param res Resources against which to resolve values
1528 * @param parser Parser of the manifest
1529 * @param flags Flags about how to parse
1530 * @param outError Human readable error if parsing fails
1531 * @return True of parsing succeeded.
1532 *
1533 * @throws XmlPullParserException
1534 * @throws IOException
1535 */
1536 private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser,
1537 int flags, String[] outError) throws XmlPullParserException, IOException {
1538 // Let ppl not abuse this mechanism by limiting the packages per APK
1539 if (parentPkg.childPackages != null && parentPkg.childPackages.size() + 2
1540 > MAX_PACKAGES_PER_APK) {
1541 outError[0] = "Maximum number of packages per APK is: " + MAX_PACKAGES_PER_APK;
1542 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1543 return false;
1544 }
1545
1546 // Make sure we have a valid child package name
1547 String childPackageName = parser.getAttributeValue(null, "package");
1548 if (validateName(childPackageName, true, false) != null) {
1549 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1550 return false;
1551 }
1552
1553 // Child packages must be unique
1554 if (childPackageName.equals(parentPkg.packageName)) {
1555 String message = "Child package name cannot be equal to parent package name: "
1556 + parentPkg.packageName;
1557 Slog.w(TAG, message);
1558 outError[0] = message;
1559 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1560 return false;
1561 }
1562
1563 // Child packages must be unique
1564 if (parentPkg.hasChildPackage(childPackageName)) {
1565 String message = "Duplicate child package:" + childPackageName;
1566 Slog.w(TAG, message);
1567 outError[0] = message;
1568 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1569 return false;
1570 }
1571
1572 // Go ahead and parse the child
1573 Package childPkg = new Package(childPackageName);
1574
1575 // Child package inherits parent version code/name/target SDK
1576 childPkg.mVersionCode = parentPkg.mVersionCode;
1577 childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
1578 childPkg.mVersionName = parentPkg.mVersionName;
1579 childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
Todd Kennedy89d60182016-03-11 11:18:32 -08001580 childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001581
1582 childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
1583 if (childPkg == null) {
1584 // If we got null then error was set during child parsing
1585 return false;
1586 }
1587
1588 // Set the parent-child relation
1589 if (parentPkg.childPackages == null) {
1590 parentPkg.childPackages = new ArrayList<>();
1591 }
1592 parentPkg.childPackages.add(childPkg);
1593 childPkg.parentPackage = parentPkg;
1594
1595 return true;
1596 }
1597
1598 /**
1599 * Parse the manifest of a <em>base APK</em>. When adding new features you
1600 * need to consider whether they should be supported by split APKs and child
1601 * packages.
1602 *
1603 * @param res The resources from which to resolve values
1604 * @param parser The manifest parser
1605 * @param flags Flags how to parse
1606 * @param outError Human readable error message
1607 * @return Parsed package or null on error.
1608 *
1609 * @throws XmlPullParserException
1610 * @throws IOException
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001611 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001612 private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001613 String[] outError) throws XmlPullParserException, IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001614 final String splitName;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001615 final String pkgName;
1616
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001617 try {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001618 Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001619 pkgName = packageSplit.first;
1620 splitName = packageSplit.second;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001621
1622 if (!TextUtils.isEmpty(splitName)) {
1623 outError[0] = "Expected base APK, but found split " + splitName;
1624 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1625 return null;
1626 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001627 } catch (PackageParserException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001628 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1629 return null;
1630 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001631
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001632 final Package pkg = new Package(pkgName);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001633
Svet Ganov354cd3c2015-12-17 11:35:04 -08001634 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 com.android.internal.R.styleable.AndroidManifest);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001636
Dianne Hackborn8472e612014-01-23 17:57:20 -08001637 pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001639 pkg.baseRevisionCode = sa.getInteger(
1640 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001641 pkg.mVersionName = sa.getNonConfigurationString(
1642 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 if (pkg.mVersionName != null) {
1644 pkg.mVersionName = pkg.mVersionName.intern();
1645 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001646
1647 pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
1648
1649 sa.recycle();
1650
1651 return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
1652 }
1653
1654 /**
1655 * This is the common parsing routing for handling parent and child
1656 * packages in a base APK. The difference between parent and child
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001657 * parsing is that some tags are not supported by child packages as
Svet Ganov354cd3c2015-12-17 11:35:04 -08001658 * well as some manifest attributes are ignored. The implementation
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001659 * assumes the calling code has already handled the manifest tag if needed
Svet Ganov354cd3c2015-12-17 11:35:04 -08001660 * (this applies to the parent only).
1661 *
1662 * @param pkg The package which to populate
1663 * @param acceptedTags Which tags to handle, null to handle all
1664 * @param res Resources against which to resolve values
1665 * @param parser Parser of the manifest
1666 * @param flags Flags about how to parse
1667 * @param outError Human readable error if parsing fails
1668 * @return The package if parsing succeeded or null.
1669 *
1670 * @throws XmlPullParserException
1671 * @throws IOException
1672 */
1673 private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
1674 XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
1675 IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001676 mParseInstrumentationArgs = null;
1677 mParseActivityArgs = null;
1678 mParseServiceArgs = null;
1679 mParseProviderArgs = null;
1680
1681 int type;
1682 boolean foundApp = false;
1683
1684 TypedArray sa = res.obtainAttributes(parser,
1685 com.android.internal.R.styleable.AndroidManifest);
1686
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001687 String str = sa.getNonConfigurationString(
1688 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
1689 if (str != null && str.length() > 0) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001690 String nameError = validateName(str, true, false);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001691 if (nameError != null && !"android".equals(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001692 outError[0] = "<manifest> specifies bad sharedUserId name \""
1693 + str + "\": " + nameError;
1694 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
1695 return null;
1696 }
1697 pkg.mSharedUserId = str.intern();
1698 pkg.mSharedUserLabel = sa.getResourceId(
1699 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
1700 }
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -08001701
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08001702 pkg.installLocation = sa.getInteger(
1703 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001704 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -07001705 pkg.applicationInfo.installLocation = pkg.installLocation;
Kenny Root7cb9be22012-05-30 15:30:37 -07001706
Alan Viverettefd274a02014-03-27 15:39:15 -07001707
Kenny Root7cb9be22012-05-30 15:30:37 -07001708 /* Set the global "forward lock" flag */
1709 if ((flags & PARSE_FORWARD_LOCK) != 0) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08001710 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
Kenny Root7cb9be22012-05-30 15:30:37 -07001711 }
1712
1713 /* Set the global "on SD card" flag */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07001714 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
Kenny Root7cb9be22012-05-30 15:30:37 -07001715 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
1716 }
1717
Svet Ganov2acf0632015-11-24 19:10:59 -08001718 if ((flags & PARSE_IS_EPHEMERAL) != 0) {
1719 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_EPHEMERAL;
1720 }
1721
Dianne Hackborn723738c2009-06-25 19:48:04 -07001722 // Resource boolean are -1, so 1 means we don't know the value.
1723 int supportsSmallScreens = 1;
1724 int supportsNormalScreens = 1;
1725 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07001726 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07001727 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -07001728 int anyDensity = 1;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001730 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -07001731 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1732 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1733 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001734 continue;
1735 }
1736
1737 String tagName = parser.getName();
Svet Ganov354cd3c2015-12-17 11:35:04 -08001738
1739 if (acceptedTags != null && !acceptedTags.contains(tagName)) {
1740 Slog.w(TAG, "Skipping unsupported element under <manifest>: "
1741 + tagName + " at " + mArchiveSourcePath + " "
1742 + parser.getPositionDescription());
1743 XmlUtils.skipCurrentTag(parser);
1744 continue;
1745 }
1746
1747 if (tagName.equals(TAG_APPLICATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001748 if (foundApp) {
1749 if (RIGID_PARSER) {
1750 outError[0] = "<manifest> has more than one <application>";
1751 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1752 return null;
1753 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07001754 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755 XmlUtils.skipCurrentTag(parser);
1756 continue;
1757 }
1758 }
1759
1760 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001761 if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 return null;
1763 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001764 } else if (tagName.equals(TAG_OVERLAY)) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001765 sa = res.obtainAttributes(parser,
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01001766 com.android.internal.R.styleable.AndroidManifestResourceOverlay);
1767 pkg.mOverlayTarget = sa.getString(
1768 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
1769 pkg.mOverlayPriority = sa.getInt(
1770 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
1771 -1);
1772 sa.recycle();
1773
1774 if (pkg.mOverlayTarget == null) {
1775 outError[0] = "<overlay> does not specify a target package";
1776 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1777 return null;
1778 }
1779 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
1780 outError[0] = "<overlay> priority must be between 0 and 9999";
1781 mParseError =
1782 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1783 return null;
1784 }
1785 XmlUtils.skipCurrentTag(parser);
1786
Svet Ganov354cd3c2015-12-17 11:35:04 -08001787 } else if (tagName.equals(TAG_KEY_SETS)) {
1788 if (!parseKeySets(pkg, res, parser, outError)) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08001789 return null;
1790 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001791 } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
1792 if (parsePermissionGroup(pkg, flags, res, parser, outError) == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001793 return null;
1794 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001795 } else if (tagName.equals(TAG_PERMISSION)) {
1796 if (parsePermission(pkg, res, parser, outError) == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 return null;
1798 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001799 } else if (tagName.equals(TAG_PERMISSION_TREE)) {
1800 if (parsePermissionTree(pkg, res, parser, outError) == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001801 return null;
1802 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001803 } else if (tagName.equals(TAG_USES_PERMISSION)) {
1804 if (!parseUsesPermission(pkg, res, parser)) {
Svetoslav96a77162015-04-03 13:58:33 -07001805 return null;
1806 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001807 } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
1808 || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
1809 if (!parseUsesPermission(pkg, res, parser)) {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07001810 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001812 } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001813 ConfigurationInfo cPref = new ConfigurationInfo();
Svet Ganov354cd3c2015-12-17 11:35:04 -08001814 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001815 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
1816 cPref.reqTouchScreen = sa.getInt(
1817 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
1818 Configuration.TOUCHSCREEN_UNDEFINED);
1819 cPref.reqKeyboardType = sa.getInt(
1820 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
1821 Configuration.KEYBOARD_UNDEFINED);
1822 if (sa.getBoolean(
1823 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
1824 false)) {
1825 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
1826 }
1827 cPref.reqNavigation = sa.getInt(
1828 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
1829 Configuration.NAVIGATION_UNDEFINED);
1830 if (sa.getBoolean(
1831 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
1832 false)) {
1833 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
1834 }
1835 sa.recycle();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001836 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001837
1838 XmlUtils.skipCurrentTag(parser);
1839
Svet Ganov354cd3c2015-12-17 11:35:04 -08001840 } else if (tagName.equals(TAG_USES_FEATURE)) {
1841 FeatureInfo fi = parseUsesFeature(res, parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001842 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
1843
Dianne Hackborn49237342009-08-27 20:08:01 -07001844 if (fi.name == null) {
1845 ConfigurationInfo cPref = new ConfigurationInfo();
1846 cPref.reqGlEsVersion = fi.reqGlEsVersion;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001847 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
Dianne Hackborn49237342009-08-27 20:08:01 -07001848 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07001849
1850 XmlUtils.skipCurrentTag(parser);
1851
Svet Ganov354cd3c2015-12-17 11:35:04 -08001852 } else if (tagName.equals(TAG_FEATURE_GROUP)) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07001853 FeatureGroupInfo group = new FeatureGroupInfo();
1854 ArrayList<FeatureInfo> features = null;
1855 final int innerDepth = parser.getDepth();
1856 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1857 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
1858 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1859 continue;
1860 }
Adam Lesinski2c72b682014-06-24 09:56:01 -07001861
Adam Lesinskid3edfde2014-08-08 17:32:44 -07001862 final String innerTagName = parser.getName();
1863 if (innerTagName.equals("uses-feature")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001864 FeatureInfo featureInfo = parseUsesFeature(res, parser);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07001865 // FeatureGroups are stricter and mandate that
1866 // any <uses-feature> declared are mandatory.
1867 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
1868 features = ArrayUtils.add(features, featureInfo);
1869 } else {
1870 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
1871 " at " + mArchiveSourcePath + " " +
1872 parser.getPositionDescription());
1873 }
1874 XmlUtils.skipCurrentTag(parser);
1875 }
1876
1877 if (features != null) {
1878 group.features = new FeatureInfo[features.size()];
1879 group.features = features.toArray(group.features);
1880 }
1881 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
Adam Lesinski2c72b682014-06-24 09:56:01 -07001882
Svet Ganov354cd3c2015-12-17 11:35:04 -08001883 } else if (tagName.equals(TAG_USES_SDK)) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001884 if (SDK_VERSION > 0) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001885 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 com.android.internal.R.styleable.AndroidManifestUsesSdk);
1887
Todd Kennedy4f657082016-06-28 10:31:05 -07001888 int minVers = 1;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001889 String minCode = null;
1890 int targetVers = 0;
1891 String targetCode = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001892
Dianne Hackborn851a5412009-05-08 12:06:44 -07001893 TypedValue val = sa.peekValue(
1894 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
1895 if (val != null) {
1896 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
1897 targetCode = minCode = val.string.toString();
1898 } else {
1899 // If it's not a string, it's an integer.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001900 targetVers = minVers = val.data;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001901 }
1902 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001903
Dianne Hackborn851a5412009-05-08 12:06:44 -07001904 val = sa.peekValue(
1905 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
1906 if (val != null) {
1907 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
Todd Kennedy89d60182016-03-11 11:18:32 -08001908 targetCode = val.string.toString();
1909 if (minCode == null) {
1910 minCode = targetCode;
1911 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07001912 } else {
1913 // If it's not a string, it's an integer.
1914 targetVers = val.data;
1915 }
1916 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001918 sa.recycle();
1919
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001920 if (minCode != null) {
Dianne Hackbornffcda102014-04-24 13:06:27 -07001921 boolean allowedCodename = false;
1922 for (String codename : SDK_CODENAMES) {
1923 if (minCode.equals(codename)) {
1924 allowedCodename = true;
1925 break;
1926 }
1927 }
1928 if (!allowedCodename) {
1929 if (SDK_CODENAMES.length > 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001930 outError[0] = "Requires development platform " + minCode
Dianne Hackbornffcda102014-04-24 13:06:27 -07001931 + " (current platform is any of "
1932 + Arrays.toString(SDK_CODENAMES) + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001933 } else {
1934 outError[0] = "Requires development platform " + minCode
1935 + " but this is a release platform.";
1936 }
1937 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1938 return null;
1939 }
Todd Kennedy6e2e7f52016-05-02 14:56:45 -07001940 pkg.applicationInfo.minSdkVersion =
1941 android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001942 } else if (minVers > SDK_VERSION) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001943 outError[0] = "Requires newer sdk version #" + minVers
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07001944 + " (current version is #" + SDK_VERSION + ")";
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001945 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1946 return null;
Todd Kennedy89d60182016-03-11 11:18:32 -08001947 } else {
Todd Kennedy6e2e7f52016-05-02 14:56:45 -07001948 pkg.applicationInfo.minSdkVersion = minVers;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001949 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07001950
Dianne Hackborn851a5412009-05-08 12:06:44 -07001951 if (targetCode != null) {
Dianne Hackbornffcda102014-04-24 13:06:27 -07001952 boolean allowedCodename = false;
1953 for (String codename : SDK_CODENAMES) {
1954 if (targetCode.equals(codename)) {
1955 allowedCodename = true;
1956 break;
1957 }
1958 }
1959 if (!allowedCodename) {
1960 if (SDK_CODENAMES.length > 0) {
Dianne Hackborn851a5412009-05-08 12:06:44 -07001961 outError[0] = "Requires development platform " + targetCode
Dianne Hackbornffcda102014-04-24 13:06:27 -07001962 + " (current platform is any of "
1963 + Arrays.toString(SDK_CODENAMES) + ")";
Dianne Hackborn851a5412009-05-08 12:06:44 -07001964 } else {
1965 outError[0] = "Requires development platform " + targetCode
1966 + " but this is a release platform.";
1967 }
1968 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
1969 return null;
1970 }
1971 // If the code matches, it definitely targets this SDK.
Dianne Hackborna96cbb42009-05-13 15:06:13 -07001972 pkg.applicationInfo.targetSdkVersion
1973 = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
1974 } else {
1975 pkg.applicationInfo.targetSdkVersion = targetVers;
Dianne Hackborn851a5412009-05-08 12:06:44 -07001976 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001977 }
1978
1979 XmlUtils.skipCurrentTag(parser);
1980
Svet Ganov354cd3c2015-12-17 11:35:04 -08001981 } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
1982 sa = res.obtainAttributes(parser,
Dianne Hackborn723738c2009-06-25 19:48:04 -07001983 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
1984
Dianne Hackborndf6e9802011-05-26 14:20:23 -07001985 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
1986 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
1987 0);
1988 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
1989 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
1990 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07001991 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
1992 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
1993 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07001994
Dianne Hackborn723738c2009-06-25 19:48:04 -07001995 // This is a trick to get a boolean and still able to detect
1996 // if a value was actually set.
1997 supportsSmallScreens = sa.getInteger(
1998 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
1999 supportsSmallScreens);
2000 supportsNormalScreens = sa.getInteger(
2001 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
2002 supportsNormalScreens);
2003 supportsLargeScreens = sa.getInteger(
2004 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
2005 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002006 supportsXLargeScreens = sa.getInteger(
2007 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
2008 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002009 resizeable = sa.getInteger(
2010 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002011 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002012 anyDensity = sa.getInteger(
2013 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
2014 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07002015
2016 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002017
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07002018 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002019
Svet Ganov354cd3c2015-12-17 11:35:04 -08002020 } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
2021 sa = res.obtainAttributes(parser,
Dianne Hackborn854060af2009-07-09 18:14:31 -07002022 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
2023
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002024 // Note: don't allow this value to be a reference to a resource
2025 // that may change.
Dianne Hackborn854060af2009-07-09 18:14:31 -07002026 String name = sa.getNonResourceString(
2027 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
2028
2029 sa.recycle();
2030
2031 if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
2032 if (pkg.protectedBroadcasts == null) {
2033 pkg.protectedBroadcasts = new ArrayList<String>();
2034 }
2035 if (!pkg.protectedBroadcasts.contains(name)) {
2036 pkg.protectedBroadcasts.add(name.intern());
2037 }
2038 }
2039
2040 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002041
Svet Ganov354cd3c2015-12-17 11:35:04 -08002042 } else if (tagName.equals(TAG_INSTRUMENTATION)) {
2043 if (parseInstrumentation(pkg, res, parser, outError) == null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002044 return null;
2045 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002046 } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
2047 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002048 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2049
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002050 String orig =sa.getNonConfigurationString(
2051 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002052 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002053 if (pkg.mOriginalPackages == null) {
2054 pkg.mOriginalPackages = new ArrayList<String>();
2055 pkg.mRealPackage = pkg.packageName;
2056 }
2057 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002058 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002059
2060 sa.recycle();
2061
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002062 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002063
Svet Ganov354cd3c2015-12-17 11:35:04 -08002064 } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
2065 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002066 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2067
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002068 String name = sa.getNonConfigurationString(
2069 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002070
2071 sa.recycle();
2072
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002073 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002074 if (pkg.mAdoptPermissions == null) {
2075 pkg.mAdoptPermissions = new ArrayList<String>();
2076 }
2077 pkg.mAdoptPermissions.add(name);
2078 }
2079
2080 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002081
Svet Ganov354cd3c2015-12-17 11:35:04 -08002082 } else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002083 // Just skip this tag
2084 XmlUtils.skipCurrentTag(parser);
2085 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002086
Svet Ganov354cd3c2015-12-17 11:35:04 -08002087 } else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002088 // Just skip this tag
2089 XmlUtils.skipCurrentTag(parser);
2090 continue;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002091 } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
Michael Wrighteaeb1902013-09-05 18:15:57 -07002092 XmlUtils.skipCurrentTag(parser);
2093 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002094
Svet Ganov354cd3c2015-12-17 11:35:04 -08002095 } else if (tagName.equals(TAG_EAT_COMMENT)) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002096 // Just skip this tag
2097 XmlUtils.skipCurrentTag(parser);
2098 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002099
Svet Ganov354cd3c2015-12-17 11:35:04 -08002100 } else if (tagName.equals(TAG_PACKAGE)) {
Svet Ganova7532cf2016-05-02 08:13:17 -07002101 if (!MULTI_PACKAGE_APK_ENABLED) {
2102 XmlUtils.skipCurrentTag(parser);
2103 continue;
2104 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002105 if (!parseBaseApkChild(pkg, res, parser, flags, outError)) {
2106 // If parsing a child failed the error is already set
2107 return null;
2108 }
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002109
2110 } else if (tagName.equals(TAG_RESTRICT_UPDATE)) {
2111 if ((flags & PARSE_IS_SYSTEM_DIR) != 0) {
2112 sa = res.obtainAttributes(parser,
2113 com.android.internal.R.styleable.AndroidManifestRestrictUpdate);
2114 final String hash = sa.getNonConfigurationString(
2115 com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0);
2116 sa.recycle();
2117
2118 pkg.restrictUpdateHash = null;
2119 if (hash != null) {
2120 final int hashLength = hash.length();
2121 final byte[] hashBytes = new byte[hashLength / 2];
2122 for (int i = 0; i < hashLength; i += 2){
2123 hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4)
2124 + Character.digit(hash.charAt(i + 1), 16));
2125 }
2126 pkg.restrictUpdateHash = hashBytes;
2127 }
2128 }
2129
2130 XmlUtils.skipCurrentTag(parser);
2131
Dianne Hackborn854060af2009-07-09 18:14:31 -07002132 } else if (RIGID_PARSER) {
2133 outError[0] = "Bad element under <manifest>: "
2134 + parser.getName();
2135 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2136 return null;
2137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002138 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002139 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002140 + " at " + mArchiveSourcePath + " "
2141 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142 XmlUtils.skipCurrentTag(parser);
2143 continue;
2144 }
2145 }
2146
2147 if (!foundApp && pkg.instrumentation.size() == 0) {
2148 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
2149 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
2150 }
2151
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002152 final int NP = PackageParser.NEW_PERMISSIONS.length;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002153 StringBuilder implicitPerms = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002154 for (int ip=0; ip<NP; ip++) {
2155 final PackageParser.NewPermissionInfo npi
2156 = PackageParser.NEW_PERMISSIONS[ip];
2157 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
2158 break;
2159 }
2160 if (!pkg.requestedPermissions.contains(npi.name)) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002161 if (implicitPerms == null) {
2162 implicitPerms = new StringBuilder(128);
2163 implicitPerms.append(pkg.packageName);
2164 implicitPerms.append(": compat added ");
2165 } else {
2166 implicitPerms.append(' ');
2167 }
2168 implicitPerms.append(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002169 pkg.requestedPermissions.add(npi.name);
2170 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002171 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002172 if (implicitPerms != null) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002173 Slog.i(TAG, implicitPerms.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002174 }
Dianne Hackborn79245122012-03-12 10:51:26 -07002175
2176 final int NS = PackageParser.SPLIT_PERMISSIONS.length;
2177 for (int is=0; is<NS; is++) {
2178 final PackageParser.SplitPermissionInfo spi
2179 = PackageParser.SPLIT_PERMISSIONS[is];
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -07002180 if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
2181 || !pkg.requestedPermissions.contains(spi.rootPerm)) {
Dianne Hackborn5e4705a2012-04-06 12:55:53 -07002182 continue;
Dianne Hackborn79245122012-03-12 10:51:26 -07002183 }
2184 for (int in=0; in<spi.newPerms.length; in++) {
2185 final String perm = spi.newPerms[in];
2186 if (!pkg.requestedPermissions.contains(perm)) {
2187 pkg.requestedPermissions.add(perm);
Dianne Hackborn79245122012-03-12 10:51:26 -07002188 }
2189 }
2190 }
2191
Dianne Hackborn723738c2009-06-25 19:48:04 -07002192 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
2193 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002194 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002195 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
2196 }
2197 if (supportsNormalScreens != 0) {
2198 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
2199 }
2200 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
2201 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002202 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002203 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
2204 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002205 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
2206 && pkg.applicationInfo.targetSdkVersion
2207 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
2208 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
2209 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002210 if (resizeable < 0 || (resizeable > 0
2211 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002212 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002213 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
2214 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002215 if (anyDensity < 0 || (anyDensity > 0
2216 && pkg.applicationInfo.targetSdkVersion
2217 >= android.os.Build.VERSION_CODES.DONUT)) {
2218 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07002219 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07002220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002221 return pkg;
2222 }
2223
Todd Kennedy27c24fb2015-09-17 16:49:25 -07002224 private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002225 FeatureInfo fi = new FeatureInfo();
2226 TypedArray sa = res.obtainAttributes(attrs,
2227 com.android.internal.R.styleable.AndroidManifestUsesFeature);
2228 // Note: don't allow this value to be a reference to a resource
2229 // that may change.
2230 fi.name = sa.getNonResourceString(
2231 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
Jeff Sharkey115d2c12016-02-15 17:25:57 -07002232 fi.version = sa.getInt(
2233 com.android.internal.R.styleable.AndroidManifestUsesFeature_version, 0);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002234 if (fi.name == null) {
2235 fi.reqGlEsVersion = sa.getInt(
2236 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
2237 FeatureInfo.GL_ES_VERSION_UNDEFINED);
2238 }
2239 if (sa.getBoolean(
2240 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) {
2241 fi.flags |= FeatureInfo.FLAG_REQUIRED;
2242 }
2243 sa.recycle();
2244 return fi;
2245 }
2246
Svet Ganov354cd3c2015-12-17 11:35:04 -08002247 private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
2248 throws XmlPullParserException, IOException {
2249 TypedArray sa = res.obtainAttributes(parser,
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002250 com.android.internal.R.styleable.AndroidManifestUsesPermission);
2251
2252 // Note: don't allow this value to be a reference to a resource
2253 // that may change.
2254 String name = sa.getNonResourceString(
2255 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002256
Christopher Tatefb0676a2013-09-16 16:34:52 -07002257 int maxSdkVersion = 0;
2258 TypedValue val = sa.peekValue(
2259 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
2260 if (val != null) {
2261 if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
2262 maxSdkVersion = val.data;
2263 }
2264 }
2265
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002266 sa.recycle();
2267
Christopher Tatefb0676a2013-09-16 16:34:52 -07002268 if ((maxSdkVersion == 0) || (maxSdkVersion >= Build.VERSION.RESOURCES_SDK_INT)) {
2269 if (name != null) {
2270 int index = pkg.requestedPermissions.indexOf(name);
2271 if (index == -1) {
2272 pkg.requestedPermissions.add(name.intern());
Christopher Tatefb0676a2013-09-16 16:34:52 -07002273 } else {
Svetoslav96a77162015-04-03 13:58:33 -07002274 Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
2275 + name + " in package: " + pkg.packageName + " at: "
2276 + parser.getPositionDescription());
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002277 }
2278 }
2279 }
2280
2281 XmlUtils.skipCurrentTag(parser);
2282 return true;
2283 }
2284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002285 private static String buildClassName(String pkg, CharSequence clsSeq,
2286 String[] outError) {
2287 if (clsSeq == null || clsSeq.length() <= 0) {
2288 outError[0] = "Empty class name in package " + pkg;
2289 return null;
2290 }
2291 String cls = clsSeq.toString();
2292 char c = cls.charAt(0);
2293 if (c == '.') {
2294 return (pkg + cls).intern();
2295 }
2296 if (cls.indexOf('.') < 0) {
2297 StringBuilder b = new StringBuilder(pkg);
2298 b.append('.');
2299 b.append(cls);
2300 return b.toString().intern();
2301 }
Todd Kennedyafb52692016-08-22 15:44:00 -07002302 return cls.intern();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002303 }
2304
2305 private static String buildCompoundName(String pkg,
2306 CharSequence procSeq, String type, String[] outError) {
2307 String proc = procSeq.toString();
2308 char c = proc.charAt(0);
2309 if (pkg != null && c == ':') {
2310 if (proc.length() < 2) {
2311 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
2312 + ": must be at least two characters";
2313 return null;
2314 }
2315 String subName = proc.substring(1);
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002316 String nameError = validateName(subName, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 if (nameError != null) {
2318 outError[0] = "Invalid " + type + " name " + proc + " in package "
2319 + pkg + ": " + nameError;
2320 return null;
2321 }
2322 return (pkg + proc).intern();
2323 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002324 String nameError = validateName(proc, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002325 if (nameError != null && !"system".equals(proc)) {
2326 outError[0] = "Invalid " + type + " name " + proc + " in package "
2327 + pkg + ": " + nameError;
2328 return null;
2329 }
2330 return proc.intern();
2331 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002333 private static String buildProcessName(String pkg, String defProc,
2334 CharSequence procSeq, int flags, String[] separateProcesses,
2335 String[] outError) {
2336 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
2337 return defProc != null ? defProc : pkg;
2338 }
2339 if (separateProcesses != null) {
2340 for (int i=separateProcesses.length-1; i>=0; i--) {
2341 String sp = separateProcesses[i];
2342 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
2343 return pkg;
2344 }
2345 }
2346 }
2347 if (procSeq == null || procSeq.length() <= 0) {
2348 return defProc;
2349 }
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002350 return buildCompoundName(pkg, procSeq, "process", outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002351 }
2352
2353 private static String buildTaskAffinityName(String pkg, String defProc,
2354 CharSequence procSeq, String[] outError) {
2355 if (procSeq == null) {
2356 return defProc;
2357 }
2358 if (procSeq.length() <= 0) {
2359 return null;
2360 }
2361 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
2362 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002363
dcashman989eb3712014-06-17 12:56:12 -07002364 private boolean parseKeySets(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002365 XmlResourceParser parser, String[] outError)
Geremy Condraf1bcca82013-01-07 22:35:24 -08002366 throws XmlPullParserException, IOException {
dcashman989eb3712014-06-17 12:56:12 -07002367 // we've encountered the 'key-sets' tag
Geremy Condraf1bcca82013-01-07 22:35:24 -08002368 // all the keys and keysets that we want must be defined here
2369 // so we're going to iterate over the parser and pull out the things we want
2370 int outerDepth = parser.getDepth();
dcashman989eb3712014-06-17 12:56:12 -07002371 int currentKeySetDepth = -1;
Geremy Condraf1bcca82013-01-07 22:35:24 -08002372 int type;
dcashman989eb3712014-06-17 12:56:12 -07002373 String currentKeySet = null;
2374 ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
2375 ArraySet<String> upgradeKeySets = new ArraySet<String>();
2376 ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
2377 ArraySet<String> improperKeySets = new ArraySet<String>();
Geremy Condraf1bcca82013-01-07 22:35:24 -08002378 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2379 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2380 if (type == XmlPullParser.END_TAG) {
dcashman989eb3712014-06-17 12:56:12 -07002381 if (parser.getDepth() == currentKeySetDepth) {
2382 currentKeySet = null;
2383 currentKeySetDepth = -1;
Kenny Root37dca152013-07-10 14:01:49 -07002384 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002385 continue;
2386 }
dcashman989eb3712014-06-17 12:56:12 -07002387 String tagName = parser.getName();
2388 if (tagName.equals("key-set")) {
2389 if (currentKeySet != null) {
dcashman5db0cd42015-05-22 15:24:40 -07002390 outError[0] = "Improperly nested 'key-set' tag at "
2391 + parser.getPositionDescription();
2392 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002393 return false;
2394 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002395 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002396 com.android.internal.R.styleable.AndroidManifestKeySet);
2397 final String keysetName = sa.getNonResourceString(
2398 com.android.internal.R.styleable.AndroidManifestKeySet_name);
2399 definedKeySets.put(keysetName, new ArraySet<String>());
2400 currentKeySet = keysetName;
2401 currentKeySetDepth = parser.getDepth();
2402 sa.recycle();
2403 } else if (tagName.equals("public-key")) {
2404 if (currentKeySet == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002405 outError[0] = "Improperly nested 'key-set' tag at "
2406 + parser.getPositionDescription();
2407 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002408 return false;
2409 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002410 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002411 com.android.internal.R.styleable.AndroidManifestPublicKey);
2412 final String publicKeyName = sa.getNonResourceString(
2413 com.android.internal.R.styleable.AndroidManifestPublicKey_name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002414 final String encodedKey = sa.getNonResourceString(
dcashman989eb3712014-06-17 12:56:12 -07002415 com.android.internal.R.styleable.AndroidManifestPublicKey_value);
2416 if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002417 outError[0] = "'public-key' " + publicKeyName + " must define a public-key value"
2418 + " on first use at " + parser.getPositionDescription();
2419 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Kenny Root37dca152013-07-10 14:01:49 -07002420 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002421 return false;
2422 } else if (encodedKey != null) {
2423 PublicKey currentKey = parsePublicKey(encodedKey);
2424 if (currentKey == null) {
2425 Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
2426 + parser.getPositionDescription() + " key-set " + currentKeySet
2427 + " will not be added to the package's defined key-sets.");
2428 sa.recycle();
2429 improperKeySets.add(currentKeySet);
2430 XmlUtils.skipCurrentTag(parser);
2431 continue;
2432 }
2433 if (publicKeys.get(publicKeyName) == null
2434 || publicKeys.get(publicKeyName).equals(currentKey)) {
2435
2436 /* public-key first definition, or matches old definition */
2437 publicKeys.put(publicKeyName, currentKey);
2438 } else {
dcashman5db0cd42015-05-22 15:24:40 -07002439 outError[0] = "Value of 'public-key' " + publicKeyName
dcashman989eb3712014-06-17 12:56:12 -07002440 + " conflicts with previously defined value at "
dcashman5db0cd42015-05-22 15:24:40 -07002441 + parser.getPositionDescription();
2442 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002443 sa.recycle();
2444 return false;
2445 }
Kenny Root37dca152013-07-10 14:01:49 -07002446 }
dcashman989eb3712014-06-17 12:56:12 -07002447 definedKeySets.get(currentKeySet).add(publicKeyName);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002448 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002449 XmlUtils.skipCurrentTag(parser);
2450 } else if (tagName.equals("upgrade-key-set")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002451 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002452 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
2453 String name = sa.getNonResourceString(
2454 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
2455 upgradeKeySets.add(name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002456 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07002457 XmlUtils.skipCurrentTag(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002458 } else if (RIGID_PARSER) {
dcashman5db0cd42015-05-22 15:24:40 -07002459 outError[0] = "Bad element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08002460 + " at " + mArchiveSourcePath + " "
dcashman5db0cd42015-05-22 15:24:40 -07002461 + parser.getPositionDescription();
2462 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Geremy Condraf1bcca82013-01-07 22:35:24 -08002463 return false;
2464 } else {
dcashman989eb3712014-06-17 12:56:12 -07002465 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08002466 + " at " + mArchiveSourcePath + " "
2467 + parser.getPositionDescription());
2468 XmlUtils.skipCurrentTag(parser);
2469 continue;
2470 }
2471 }
dcashman989eb3712014-06-17 12:56:12 -07002472 Set<String> publicKeyNames = publicKeys.keySet();
2473 if (publicKeyNames.removeAll(definedKeySets.keySet())) {
dcashman5db0cd42015-05-22 15:24:40 -07002474 outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
2475 + "'key-set' and 'public-key' names must be distinct.";
2476 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002477 return false;
2478 }
2479 owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
2480 for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) {
2481 final String keySetName = e.getKey();
2482 if (e.getValue().size() == 0) {
2483 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
2484 + "'key-set' " + keySetName + " has no valid associated 'public-key'."
2485 + " Not including in package's defined key-sets.");
2486 continue;
2487 } else if (improperKeySets.contains(keySetName)) {
2488 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
2489 + "'key-set' " + keySetName + " contained improper 'public-key'"
2490 + " tags. Not including in package's defined key-sets.");
2491 continue;
2492 }
2493 owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
2494 for (String s : e.getValue()) {
2495 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
Geremy Condraf1bcca82013-01-07 22:35:24 -08002496 }
2497 }
dcashman989eb3712014-06-17 12:56:12 -07002498 if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
2499 owner.mUpgradeKeySets = upgradeKeySets;
2500 } else {
dcashman5db0cd42015-05-22 15:24:40 -07002501 outError[0] ="Package" + owner.packageName + " AndroidManifext.xml "
2502 + "does not define all 'upgrade-key-set's .";
2503 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002504 return false;
2505 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002506 return true;
2507 }
2508
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07002509 private PermissionGroup parsePermissionGroup(Package owner, int flags, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002510 XmlResourceParser parser, String[] outError)
2511 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002512 PermissionGroup perm = new PermissionGroup(owner);
2513
Svet Ganov354cd3c2015-12-17 11:35:04 -08002514 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002515 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002516 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07002517 "<permission-group>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002518 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
2519 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002520 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07002521 com.android.internal.R.styleable.AndroidManifestPermissionGroup_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08002522 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
2523 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 sa.recycle();
2525 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2526 return null;
2527 }
2528
2529 perm.info.descriptionRes = sa.getResourceId(
2530 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
2531 0);
Dianne Hackborn7454d3b2012-09-12 17:22:00 -07002532 perm.info.flags = sa.getInt(
2533 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07002534 perm.info.priority = sa.getInt(
2535 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
Dianne Hackborn99222d22012-05-06 16:30:15 -07002536 if (perm.info.priority > 0 && (flags&PARSE_IS_SYSTEM) == 0) {
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07002537 perm.info.priority = 0;
2538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002539
2540 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002541
Svet Ganov354cd3c2015-12-17 11:35:04 -08002542 if (!parseAllMetaData(res, parser, "<permission-group>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002543 outError)) {
2544 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2545 return null;
2546 }
2547
2548 owner.permissionGroups.add(perm);
2549
2550 return perm;
2551 }
2552
2553 private Permission parsePermission(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002554 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002555 throws XmlPullParserException, IOException {
2556 Permission perm = new Permission(owner);
2557
Svet Ganov354cd3c2015-12-17 11:35:04 -08002558 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002559 com.android.internal.R.styleable.AndroidManifestPermission);
2560
2561 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07002562 "<permission>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002563 com.android.internal.R.styleable.AndroidManifestPermission_name,
2564 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002565 com.android.internal.R.styleable.AndroidManifestPermission_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07002566 com.android.internal.R.styleable.AndroidManifestPermission_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08002567 com.android.internal.R.styleable.AndroidManifestPermission_logo,
2568 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002569 sa.recycle();
2570 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2571 return null;
2572 }
2573
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002574 // Note: don't allow this value to be a reference to a resource
2575 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002576 perm.info.group = sa.getNonResourceString(
2577 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
2578 if (perm.info.group != null) {
2579 perm.info.group = perm.info.group.intern();
2580 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002582 perm.info.descriptionRes = sa.getResourceId(
2583 com.android.internal.R.styleable.AndroidManifestPermission_description,
2584 0);
2585
2586 perm.info.protectionLevel = sa.getInt(
2587 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
2588 PermissionInfo.PROTECTION_NORMAL);
2589
Dianne Hackborn2ca2c872012-09-16 16:03:36 -07002590 perm.info.flags = sa.getInt(
2591 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
2592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 sa.recycle();
Dianne Hackborne639da72012-02-21 15:11:13 -08002594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002595 if (perm.info.protectionLevel == -1) {
2596 outError[0] = "<permission> does not specify protectionLevel";
2597 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2598 return null;
2599 }
Dianne Hackborne639da72012-02-21 15:11:13 -08002600
2601 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
2602
2603 if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_FLAGS) != 0) {
2604 if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
2605 PermissionInfo.PROTECTION_SIGNATURE) {
2606 outError[0] = "<permission> protectionLevel specifies a flag but is "
2607 + "not based on signature type";
2608 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2609 return null;
2610 }
2611 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002612
Svet Ganov354cd3c2015-12-17 11:35:04 -08002613 if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002614 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2615 return null;
2616 }
2617
2618 owner.permissions.add(perm);
2619
2620 return perm;
2621 }
2622
2623 private Permission parsePermissionTree(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002624 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002625 throws XmlPullParserException, IOException {
2626 Permission perm = new Permission(owner);
2627
Svet Ganov354cd3c2015-12-17 11:35:04 -08002628 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 com.android.internal.R.styleable.AndroidManifestPermissionTree);
2630
2631 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07002632 "<permission-tree>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002633 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
2634 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002635 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07002636 com.android.internal.R.styleable.AndroidManifestPermissionTree_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08002637 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
2638 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002639 sa.recycle();
2640 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2641 return null;
2642 }
2643
2644 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002646 int index = perm.info.name.indexOf('.');
2647 if (index > 0) {
2648 index = perm.info.name.indexOf('.', index+1);
2649 }
2650 if (index < 0) {
2651 outError[0] = "<permission-tree> name has less than three segments: "
2652 + perm.info.name;
2653 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2654 return null;
2655 }
2656
2657 perm.info.descriptionRes = 0;
2658 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
2659 perm.tree = true;
2660
Svet Ganov354cd3c2015-12-17 11:35:04 -08002661 if (!parseAllMetaData(res, parser, "<permission-tree>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002662 outError)) {
2663 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2664 return null;
2665 }
2666
2667 owner.permissions.add(perm);
2668
2669 return perm;
2670 }
2671
2672 private Instrumentation parseInstrumentation(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002673 XmlResourceParser parser, String[] outError)
2674 throws XmlPullParserException, IOException {
2675 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002676 com.android.internal.R.styleable.AndroidManifestInstrumentation);
2677
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002678 if (mParseInstrumentationArgs == null) {
2679 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
2680 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
2681 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07002682 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07002683 com.android.internal.R.styleable.AndroidManifestInstrumentation_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08002684 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
2685 com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002686 mParseInstrumentationArgs.tag = "<instrumentation>";
2687 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002688
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002689 mParseInstrumentationArgs.sa = sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002690
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002691 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
2692 new InstrumentationInfo());
2693 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002694 sa.recycle();
2695 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2696 return null;
2697 }
2698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002699 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002700 // Note: don't allow this value to be a reference to a resource
2701 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002702 str = sa.getNonResourceString(
2703 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
2704 a.info.targetPackage = str != null ? str.intern() : null;
2705
2706 a.info.handleProfiling = sa.getBoolean(
2707 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
2708 false);
2709
2710 a.info.functionalTest = sa.getBoolean(
2711 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
2712 false);
2713
2714 sa.recycle();
2715
2716 if (a.info.targetPackage == null) {
2717 outError[0] = "<instrumentation> does not specify targetPackage";
2718 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2719 return null;
2720 }
2721
Svet Ganov354cd3c2015-12-17 11:35:04 -08002722 if (!parseAllMetaData(res, parser, "<instrumentation>", a,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002723 outError)) {
2724 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2725 return null;
2726 }
2727
2728 owner.instrumentation.add(a);
2729
2730 return a;
2731 }
2732
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002733 /**
2734 * Parse the {@code application} XML tree at the current parse location in a
2735 * <em>base APK</em> manifest.
2736 * <p>
2737 * When adding new features, carefully consider if they should also be
2738 * supported by split APKs.
2739 */
2740 private boolean parseBaseApplication(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002741 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002742 throws XmlPullParserException, IOException {
2743 final ApplicationInfo ai = owner.applicationInfo;
2744 final String pkgName = owner.applicationInfo.packageName;
2745
Svet Ganov354cd3c2015-12-17 11:35:04 -08002746 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002747 com.android.internal.R.styleable.AndroidManifestApplication);
2748
Todd Kennedybb8a42d2016-06-02 14:13:56 -07002749 if (!parsePackageItemInfo(owner, ai, outError,
2750 "<application>", sa, false /*nameRequired*/,
2751 com.android.internal.R.styleable.AndroidManifestApplication_name,
2752 com.android.internal.R.styleable.AndroidManifestApplication_label,
2753 com.android.internal.R.styleable.AndroidManifestApplication_icon,
2754 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon,
2755 com.android.internal.R.styleable.AndroidManifestApplication_logo,
2756 com.android.internal.R.styleable.AndroidManifestApplication_banner)) {
2757 sa.recycle();
2758 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2759 return false;
2760 }
2761
2762 if (ai.name != null) {
Todd Kennedyafb52692016-08-22 15:44:00 -07002763 ai.className = ai.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002764 }
2765
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002766 String manageSpaceActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002767 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
2768 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002769 if (manageSpaceActivity != null) {
2770 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
2771 outError);
2772 }
2773
Christopher Tate181fafa2009-05-14 11:12:14 -07002774 boolean allowBackup = sa.getBoolean(
2775 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
2776 if (allowBackup) {
2777 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07002778
Christopher Tate43fbc5f2016-02-17 18:00:48 -08002779 // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
2780 // and restoreAnyVersion are only relevant if backup is possible for the
2781 // given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002782 String backupAgent = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002783 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
2784 Configuration.NATIVE_CONFIG_VERSION);
Christopher Tate181fafa2009-05-14 11:12:14 -07002785 if (backupAgent != null) {
2786 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07002787 if (DEBUG_BACKUP) {
2788 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002789 + " from " + pkgName + "+" + backupAgent);
2790 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07002791
2792 if (sa.getBoolean(
2793 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
2794 true)) {
2795 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
2796 }
2797 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08002798 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
2799 false)) {
2800 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
2801 }
Christopher Tated1de2562014-06-17 17:12:35 -07002802 if (sa.getBoolean(
2803 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
2804 false)) {
2805 ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
2806 }
Christopher Tate43fbc5f2016-02-17 18:00:48 -08002807 if (sa.getBoolean(
2808 com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
2809 false)) {
2810 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
2811 }
Christopher Tate181fafa2009-05-14 11:12:14 -07002812 }
Matthew Williams303650c2015-04-17 18:22:51 -07002813
2814 TypedValue v = sa.peekValue(
2815 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
2816 if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
2817 if (DEBUG_BACKUP) {
2818 Slog.v(TAG, "fullBackupContent specified as boolean=" +
2819 (v.data == 0 ? "false" : "true"));
2820 }
2821 // "false" => -1, "true" => 0
2822 ai.fullBackupContent = (v.data == 0 ? -1 : 0);
2823 }
2824 if (DEBUG_BACKUP) {
2825 Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
2826 }
Christopher Tate181fafa2009-05-14 11:12:14 -07002827 }
Christopher Tate4a627c72011-04-01 14:43:32 -07002828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002829 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08002830 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002831 ai.descriptionRes = sa.getResourceId(
2832 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
2833
2834 if ((flags&PARSE_IS_SYSTEM) != 0) {
2835 if (sa.getBoolean(
2836 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
2837 false)) {
2838 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
2839 }
Amith Yamasani0d8750d2013-05-01 15:25:28 -07002840 }
2841
2842 if (sa.getBoolean(
2843 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
2844 false)) {
2845 owner.mRequiredForAllUsers = true;
Amith Yamasanie993ae12013-04-15 13:42:57 -07002846 }
2847
2848 String restrictedAccountType = sa.getString(com.android.internal.R.styleable
2849 .AndroidManifestApplication_restrictedAccountType);
2850 if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
2851 owner.mRestrictedAccountType = restrictedAccountType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002852 }
2853
Amith Yamasaniccbe3892013-04-12 17:52:42 -07002854 String requiredAccountType = sa.getString(com.android.internal.R.styleable
2855 .AndroidManifestApplication_requiredAccountType);
2856 if (requiredAccountType != null && requiredAccountType.length() > 0) {
2857 owner.mRequiredAccountType = requiredAccountType;
2858 }
2859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002860 if (sa.getBoolean(
2861 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
2862 false)) {
2863 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
2864 }
2865
2866 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07002867 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08002868 false)) {
2869 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
2870 }
2871
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002872 owner.baseHardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07002873 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07002874 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Alan Viveretted70b9e72015-05-27 14:29:20 -07002875 if (owner.baseHardwareAccelerated) {
2876 ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
2877 }
Romain Guy812ccbe2010-06-01 14:07:24 -07002878
2879 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002880 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
2881 true)) {
2882 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
2883 }
2884
2885 if (sa.getBoolean(
2886 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
2887 false)) {
2888 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
2889 }
2890
2891 if (sa.getBoolean(
2892 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
2893 true)) {
2894 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
2895 }
2896
Svet Ganov354cd3c2015-12-17 11:35:04 -08002897 // The parent package controls installation, hence specify test only installs.
2898 if (owner.parentPackage == null) {
2899 if (sa.getBoolean(
2900 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
2901 false)) {
2902 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
2903 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07002904 }
2905
Jason parksa3cdaa52011-01-13 14:15:43 -06002906 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08002907 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06002908 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08002909 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06002910 }
2911
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07002912 if (sa.getBoolean(
Alex Klyubin01a959d2015-03-18 10:05:45 -07002913 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
2914 true)) {
2915 ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
2916 }
2917
2918 if (sa.getBoolean(
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07002919 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
2920 false /* default is no RTL support*/)) {
2921 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
2922 }
2923
Narayan Kamath589a1bc2014-07-03 14:43:26 +01002924 if (sa.getBoolean(
2925 com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
2926 false)) {
2927 ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
2928 }
2929
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07002930 if (sa.getBoolean(
2931 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
2932 true)) {
2933 ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
2934 }
2935
Todd Kennedyd022ac22016-04-13 10:49:29 -07002936 if (sa.getBoolean(
2937 R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
2938 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06002939 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
Jeff Sharkeye17ac152015-11-06 22:40:29 -08002940 }
Todd Kennedyd022ac22016-04-13 10:49:29 -07002941 if (sa.getBoolean(
2942 R.styleable.AndroidManifestApplication_directBootAware,
2943 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06002944 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08002945 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08002946
Wale Ogunwale6afdf912016-01-30 13:01:33 -08002947 if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity,
2948 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N)) {
2949 ai.privateFlags |= PRIVATE_FLAG_RESIZEABLE_ACTIVITIES;
2950 }
2951
Chad Brubakerc845b2a2016-05-13 14:09:27 -07002952 ai.networkSecurityConfigRes = sa.getResourceId(
2953 com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig,
2954 0);
2955
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002956 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002957 str = sa.getNonConfigurationString(
2958 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002959 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
2960
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002961 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
2962 str = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002963 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
2964 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002965 } else {
2966 // Some older apps have been seen to use a resource reference
2967 // here that on older builds was ignored (with a warning). We
2968 // need to continue to do this for them so they don't break.
2969 str = sa.getNonResourceString(
2970 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
2971 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002972 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
2973 str, outError);
2974
2975 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002976 CharSequence pname;
2977 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
2978 pname = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07002979 com.android.internal.R.styleable.AndroidManifestApplication_process,
2980 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07002981 } else {
2982 // Some older apps have been seen to use a resource reference
2983 // here that on older builds was ignored (with a warning). We
2984 // need to continue to do this for them so they don't break.
2985 pname = sa.getNonResourceString(
2986 com.android.internal.R.styleable.AndroidManifestApplication_process);
2987 }
2988 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002989 flags, mSeparateProcesses, outError);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002990
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002991 ai.enabled = sa.getBoolean(
2992 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002993
Jose Lima12d0b4c2014-03-14 16:55:12 -07002994 if (sa.getBoolean(
2995 com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
2996 ai.flags |= ApplicationInfo.FLAG_IS_GAME;
2997 }
2998
Dianne Hackborn02486b12010-08-26 14:18:37 -07002999 if (false) {
3000 if (sa.getBoolean(
3001 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
3002 false)) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08003003 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07003004
3005 // A heavy-weight application can not be in a custom process.
3006 // We can do direct compare because we intern all strings.
3007 if (ai.processName != null && ai.processName != ai.packageName) {
3008 outError[0] = "cantSaveState applications can not use custom processes";
3009 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003010 }
3011 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003012 }
3013
Adam Powell269248d2011-08-02 10:26:54 -07003014 ai.uiOptions = sa.getInt(
3015 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
3016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003017 sa.recycle();
3018
3019 if (outError[0] != null) {
3020 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3021 return false;
3022 }
3023
3024 final int innerDepth = parser.getDepth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003025 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07003026 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3027 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3028 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003029 continue;
3030 }
3031
3032 String tagName = parser.getName();
3033 if (tagName.equals("activity")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003034 Activity a = parseActivity(owner, res, parser, flags, outError, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003035 owner.baseHardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003036 if (a == null) {
3037 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3038 return false;
3039 }
3040
3041 owner.activities.add(a);
3042
3043 } else if (tagName.equals("receiver")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003044 Activity a = parseActivity(owner, res, parser, flags, outError, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003045 if (a == null) {
3046 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3047 return false;
3048 }
3049
3050 owner.receivers.add(a);
3051
3052 } else if (tagName.equals("service")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003053 Service s = parseService(owner, res, parser, flags, outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 if (s == null) {
3055 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3056 return false;
3057 }
3058
3059 owner.services.add(s);
3060
3061 } else if (tagName.equals("provider")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003062 Provider p = parseProvider(owner, res, parser, flags, outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003063 if (p == null) {
3064 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3065 return false;
3066 }
3067
3068 owner.providers.add(p);
3069
3070 } else if (tagName.equals("activity-alias")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003071 Activity a = parseActivityAlias(owner, res, parser, flags, outError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003072 if (a == null) {
3073 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3074 return false;
3075 }
3076
3077 owner.activities.add(a);
3078
3079 } else if (parser.getName().equals("meta-data")) {
3080 // note: application meta-data is stored off to the side, so it can
3081 // remain null in the primary copy (we like to avoid extra copies because
3082 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003083 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003084 outError)) == null) {
3085 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3086 return false;
3087 }
3088
Dianne Hackbornc895be72013-03-11 17:48:43 -07003089 } else if (tagName.equals("library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003090 sa = res.obtainAttributes(parser,
Dianne Hackbornc895be72013-03-11 17:48:43 -07003091 com.android.internal.R.styleable.AndroidManifestLibrary);
3092
3093 // Note: don't allow this value to be a reference to a resource
3094 // that may change.
3095 String lname = sa.getNonResourceString(
3096 com.android.internal.R.styleable.AndroidManifestLibrary_name);
3097
3098 sa.recycle();
3099
3100 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003101 lname = lname.intern();
3102 if (!ArrayUtils.contains(owner.libraryNames, lname)) {
3103 owner.libraryNames = ArrayUtils.add(owner.libraryNames, lname);
Dianne Hackbornc895be72013-03-11 17:48:43 -07003104 }
3105 }
3106
3107 XmlUtils.skipCurrentTag(parser);
3108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003109 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003110 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003111 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3112
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003113 // Note: don't allow this value to be a reference to a resource
3114 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003115 String lname = sa.getNonResourceString(
3116 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07003117 boolean req = sa.getBoolean(
3118 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3119 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003120
3121 sa.recycle();
3122
Dianne Hackborn49237342009-08-27 20:08:01 -07003123 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003124 lname = lname.intern();
Dianne Hackborn49237342009-08-27 20:08:01 -07003125 if (req) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003126 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07003127 } else {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003128 owner.usesOptionalLibraries = ArrayUtils.add(
3129 owner.usesOptionalLibraries, lname);
3130 }
3131 }
3132
3133 XmlUtils.skipCurrentTag(parser);
3134
3135 } else if (tagName.equals("uses-package")) {
3136 // Dependencies for app installers; we don't currently try to
3137 // enforce this.
3138 XmlUtils.skipCurrentTag(parser);
3139
3140 } else {
3141 if (!RIGID_PARSER) {
3142 Slog.w(TAG, "Unknown element under <application>: " + tagName
3143 + " at " + mArchiveSourcePath + " "
3144 + parser.getPositionDescription());
3145 XmlUtils.skipCurrentTag(parser);
3146 continue;
3147 } else {
3148 outError[0] = "Bad element under <application>: " + tagName;
3149 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3150 return false;
3151 }
3152 }
3153 }
3154
Narayan Kamathb12dcfb2015-03-30 11:31:04 +01003155 modifySharedLibrariesForBackwardCompatibility(owner);
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00003156
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003157 if (hasDomainURLs(owner)) {
3158 owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3159 } else {
3160 owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3161 }
3162
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003163 return true;
3164 }
3165
Narayan Kamathb12dcfb2015-03-30 11:31:04 +01003166 private static void modifySharedLibrariesForBackwardCompatibility(Package owner) {
3167 // "org.apache.http.legacy" is now a part of the boot classpath so it doesn't need
3168 // to be an explicit dependency.
3169 //
3170 // A future change will remove this library from the boot classpath, at which point
3171 // all apps that target SDK 21 and earlier will have it automatically added to their
3172 // dependency lists.
3173 owner.usesLibraries = ArrayUtils.remove(owner.usesLibraries, "org.apache.http.legacy");
3174 owner.usesOptionalLibraries = ArrayUtils.remove(owner.usesOptionalLibraries,
3175 "org.apache.http.legacy");
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00003176 }
3177
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003178 /**
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003179 * 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 -07003180 */
3181 private static boolean hasDomainURLs(Package pkg) {
3182 if (pkg == null || pkg.activities == null) return false;
3183 final ArrayList<Activity> activities = pkg.activities;
3184 final int countActivities = activities.size();
3185 for (int n=0; n<countActivities; n++) {
3186 Activity activity = activities.get(n);
3187 ArrayList<ActivityIntentInfo> filters = activity.intents;
3188 if (filters == null) continue;
3189 final int countFilters = filters.size();
3190 for (int m=0; m<countFilters; m++) {
3191 ActivityIntentInfo aii = filters.get(m);
3192 if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003193 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003194 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
3195 aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
3196 return true;
3197 }
3198 }
3199 }
3200 return false;
3201 }
3202
3203 /**
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003204 * Parse the {@code application} XML tree at the current parse location in a
3205 * <em>split APK</em> manifest.
3206 * <p>
3207 * Note that split APKs have many more restrictions on what they're capable
3208 * of doing, so many valid features of a base APK have been carefully
3209 * omitted here.
3210 */
Svet Ganov354cd3c2015-12-17 11:35:04 -08003211 private boolean parseSplitApplication(Package owner, Resources res, XmlResourceParser parser,
3212 int flags, int splitIndex, String[] outError)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003213 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003214 TypedArray sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003215 com.android.internal.R.styleable.AndroidManifestApplication);
3216
3217 if (sa.getBoolean(
3218 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
3219 owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
3220 }
3221
3222 final int innerDepth = parser.getDepth();
3223 int type;
3224 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3225 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3226 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3227 continue;
3228 }
3229
3230 String tagName = parser.getName();
3231 if (tagName.equals("activity")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003232 Activity a = parseActivity(owner, res, parser, flags, outError, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003233 owner.baseHardwareAccelerated);
3234 if (a == null) {
3235 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3236 return false;
3237 }
3238
3239 owner.activities.add(a);
3240
3241 } else if (tagName.equals("receiver")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003242 Activity a = parseActivity(owner, res, parser, flags, outError, true, false);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003243 if (a == null) {
3244 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3245 return false;
3246 }
3247
3248 owner.receivers.add(a);
3249
3250 } else if (tagName.equals("service")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003251 Service s = parseService(owner, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003252 if (s == null) {
3253 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3254 return false;
3255 }
3256
3257 owner.services.add(s);
3258
3259 } else if (tagName.equals("provider")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003260 Provider p = parseProvider(owner, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003261 if (p == null) {
3262 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3263 return false;
3264 }
3265
3266 owner.providers.add(p);
3267
3268 } else if (tagName.equals("activity-alias")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003269 Activity a = parseActivityAlias(owner, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003270 if (a == null) {
3271 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3272 return false;
3273 }
3274
3275 owner.activities.add(a);
3276
3277 } else if (parser.getName().equals("meta-data")) {
3278 // note: application meta-data is stored off to the side, so it can
3279 // remain null in the primary copy (we like to avoid extra copies because
3280 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003281 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003282 outError)) == null) {
3283 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3284 return false;
3285 }
3286
3287 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003288 sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003289 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3290
3291 // Note: don't allow this value to be a reference to a resource
3292 // that may change.
3293 String lname = sa.getNonResourceString(
3294 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
3295 boolean req = sa.getBoolean(
3296 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3297 true);
3298
3299 sa.recycle();
3300
3301 if (lname != null) {
3302 lname = lname.intern();
3303 if (req) {
3304 // Upgrade to treat as stronger constraint
3305 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
3306 owner.usesOptionalLibraries = ArrayUtils.remove(
3307 owner.usesOptionalLibraries, lname);
3308 } else {
3309 // Ignore if someone already defined as required
3310 if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
3311 owner.usesOptionalLibraries = ArrayUtils.add(
3312 owner.usesOptionalLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07003313 }
3314 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 }
3316
3317 XmlUtils.skipCurrentTag(parser);
3318
Dianne Hackborncef65ee2010-09-30 18:27:22 -07003319 } else if (tagName.equals("uses-package")) {
3320 // Dependencies for app installers; we don't currently try to
3321 // enforce this.
3322 XmlUtils.skipCurrentTag(parser);
3323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 } else {
3325 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003326 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003327 + " at " + mArchiveSourcePath + " "
3328 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003329 XmlUtils.skipCurrentTag(parser);
3330 continue;
3331 } else {
3332 outError[0] = "Bad element under <application>: " + tagName;
3333 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3334 return false;
3335 }
3336 }
3337 }
3338
3339 return true;
3340 }
3341
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003342 private static boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
3343 String[] outError, String tag, TypedArray sa, boolean nameRequired,
3344 int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) {
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003345 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003346 if (name == null) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003347 if (nameRequired) {
3348 outError[0] = tag + " does not specify android:name";
3349 return false;
3350 }
3351 } else {
3352 outInfo.name
3353 = buildClassName(owner.applicationInfo.packageName, name, outError);
3354 if (outInfo.name == null) {
3355 return false;
3356 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003357 }
3358
Todd Kennedya83bfca2016-06-03 07:52:17 -07003359 final boolean useRoundIcon =
3360 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
3361 int roundIconVal = useRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003362 if (roundIconVal != 0) {
3363 outInfo.icon = roundIconVal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003364 outInfo.nonLocalizedLabel = null;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003365 } else {
3366 int iconVal = sa.getResourceId(iconRes, 0);
3367 if (iconVal != 0) {
3368 outInfo.icon = iconVal;
3369 outInfo.nonLocalizedLabel = null;
3370 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003371 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003372
Adam Powell81cd2e92010-04-21 16:35:18 -07003373 int logoVal = sa.getResourceId(logoRes, 0);
3374 if (logoVal != 0) {
3375 outInfo.logo = logoVal;
3376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003377
Jose Limaf78e3122014-03-06 12:13:15 -08003378 int bannerVal = sa.getResourceId(bannerRes, 0);
3379 if (bannerVal != 0) {
3380 outInfo.banner = bannerVal;
3381 }
3382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003383 TypedValue v = sa.peekValue(labelRes);
3384 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
3385 outInfo.nonLocalizedLabel = v.coerceToString();
3386 }
3387
3388 outInfo.packageName = owner.packageName;
3389
3390 return true;
3391 }
3392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003393 private Activity parseActivity(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003394 XmlResourceParser parser, int flags, String[] outError,
Romain Guy529b60a2010-08-03 18:05:47 -07003395 boolean receiver, boolean hardwareAccelerated)
3396 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003397 TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003398
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003399 if (mParseActivityArgs == null) {
3400 mParseActivityArgs = new ParseComponentArgs(owner, outError,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003401 R.styleable.AndroidManifestActivity_name,
3402 R.styleable.AndroidManifestActivity_label,
3403 R.styleable.AndroidManifestActivity_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003404 R.styleable.AndroidManifestActivity_roundIcon,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003405 R.styleable.AndroidManifestActivity_logo,
3406 R.styleable.AndroidManifestActivity_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003407 mSeparateProcesses,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003408 R.styleable.AndroidManifestActivity_process,
3409 R.styleable.AndroidManifestActivity_description,
3410 R.styleable.AndroidManifestActivity_enabled);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003411 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003412
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003413 mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
3414 mParseActivityArgs.sa = sa;
3415 mParseActivityArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003416
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003417 Activity a = new Activity(mParseActivityArgs, new ActivityInfo());
3418 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003419 sa.recycle();
3420 return null;
3421 }
3422
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003423 boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003424 if (setExported) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003425 a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426 }
3427
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003428 a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003429
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003430 a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
Adam Powell269248d2011-08-02 10:26:54 -07003431 a.info.applicationInfo.uiOptions);
3432
Adam Powelldd8fab22012-03-22 17:47:27 -07003433 String parentName = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003434 R.styleable.AndroidManifestActivity_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003435 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07003436 if (parentName != null) {
3437 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
3438 if (outError[0] == null) {
3439 a.info.parentActivityName = parentClassName;
3440 } else {
3441 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
3442 parentName);
3443 outError[0] = null;
3444 }
3445 }
3446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003447 String str;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003448 str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003449 if (str == null) {
3450 a.info.permission = owner.applicationInfo.permission;
3451 } else {
3452 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
3453 }
3454
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003455 str = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003456 R.styleable.AndroidManifestActivity_taskAffinity,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003457 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003458 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
3459 owner.applicationInfo.taskAffinity, str, outError);
3460
3461 a.info.flags = 0;
3462 if (sa.getBoolean(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003463 R.styleable.AndroidManifestActivity_multiprocess, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003464 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
3465 }
3466
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003467 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
3469 }
3470
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003471 if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003472 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
3473 }
3474
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003475 if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003476 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
3477 }
3478
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003479 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003480 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
3481 }
3482
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003483 if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003484 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
3485 }
3486
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003487 if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003488 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
3489 }
3490
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003491 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003492 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
3493 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
3494 }
3495
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003496 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
Dianne Hackbornffa42482009-09-23 22:20:11 -07003497 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
3498 }
3499
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07003500 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
3501 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
3502 a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Craig Mautner5962b122012-10-05 14:45:52 -07003503 }
3504
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003505 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
Daniel Sandler613dde42010-06-21 13:46:39 -04003506 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
3507 }
Craig Mautner5962b122012-10-05 14:45:52 -07003508
Fyodor Kupolov4f5de342015-08-25 10:08:45 -07003509 if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
3510 a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
Fyodor Kupolov703d1c42015-01-27 11:59:00 -08003511 }
3512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003513 if (!receiver) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003514 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07003515 hardwareAccelerated)) {
3516 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
3517 }
3518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003519 a.info.launchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003520 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
Craig Mautner2dac0562014-05-06 09:06:44 -07003521 a.info.documentLaunchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003522 R.styleable.AndroidManifestActivity_documentLaunchMode,
Craig Mautner2dac0562014-05-06 09:06:44 -07003523 ActivityInfo.DOCUMENT_LAUNCH_NONE);
Craig Mautnerffcfcaa2014-06-05 09:54:38 -07003524 a.info.maxRecents = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003525 R.styleable.AndroidManifestActivity_maxRecents,
Dianne Hackborn852975d2014-08-22 17:42:43 -07003526 ActivityManager.getDefaultAppRecentsLimitStatic());
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003527 a.info.configChanges = sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003528 a.info.softInputMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003529 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
Craig Mautner2dac0562014-05-06 09:06:44 -07003530
Craig Mautner43e52ed2014-06-16 17:18:52 -07003531 a.info.persistableMode = sa.getInteger(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003532 R.styleable.AndroidManifestActivity_persistableMode,
Craig Mautner43e52ed2014-06-16 17:18:52 -07003533 ActivityInfo.PERSIST_ROOT_ONLY);
Craig Mautner2dac0562014-05-06 09:06:44 -07003534
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003535 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07003536 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
3537 }
3538
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003539 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07003540 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
3541 }
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07003542
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003543 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07003544 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
3545 }
Dianne Hackborna4e102e2014-09-04 22:52:27 -07003546
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003547 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
Dianne Hackborna4e102e2014-09-04 22:52:27 -07003548 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
3549 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003550
Wale Ogunwaled26176f2016-01-25 20:04:04 -08003551 a.info.screenOrientation = sa.getInt(
3552 R.styleable.AndroidManifestActivity_screenOrientation,
3553 SCREEN_ORIENTATION_UNSPECIFIED);
Wale Ogunwale6a591362015-10-05 20:18:27 -07003554
Wale Ogunwaled26176f2016-01-25 20:04:04 -08003555 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale163828d2016-02-01 11:48:19 -08003556 final boolean appDefault = (owner.applicationInfo.privateFlags
3557 & PRIVATE_FLAG_RESIZEABLE_ACTIVITIES) != 0;
Andrii Kulian3f8dc152016-05-17 19:07:24 -07003558 // This flag is used to workaround the issue with ignored resizeableActivity param when
3559 // either targetSdkVersion is not set at all or <uses-sdk> tag is below <application>
3560 // tag in AndroidManifest. If this param was explicitly set to 'false' we need to set
3561 // corresponding resizeMode regardless of targetSdkVersion value at this point in time.
3562 final boolean resizeableSetExplicitly
3563 = sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity);
Wale Ogunwale163828d2016-02-01 11:48:19 -08003564 final boolean resizeable = sa.getBoolean(
3565 R.styleable.AndroidManifestActivity_resizeableActivity, appDefault);
3566
3567 if (resizeable) {
3568 if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
3569 false)) {
3570 a.info.resizeMode = RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
3571 } else {
3572 a.info.resizeMode = RESIZE_MODE_RESIZEABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08003573 }
Andrii Kulian3f8dc152016-05-17 19:07:24 -07003574 } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N
3575 || resizeableSetExplicitly) {
Wale Ogunwale163828d2016-02-01 11:48:19 -08003576 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale508ff552016-02-15 19:31:50 -08003577 } else if (!a.info.isFixedOrientation() && (a.info.flags & FLAG_IMMERSIVE) == 0) {
Wale Ogunwaled829d362016-02-10 19:24:49 -08003578 a.info.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08003579 }
3580
3581 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
Wale Ogunwaled26176f2016-01-25 20:04:04 -08003582 a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08003583 }
Wale Ogunwaleb60692e2015-10-24 12:35:56 -07003584
Craig Mautner15df08a2015-04-01 12:17:18 -07003585 a.info.lockTaskLaunchMode =
3586 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003587
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003588 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
3589 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07003590 false);
Ruben Brunkf56c9f42016-04-22 18:20:55 -07003591
3592 a.info.requestedVrComponent =
3593 sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003594 } else {
3595 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
3596 a.info.configChanges = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003597
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08003598 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07003599 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003600 if (a.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003601 Slog.w(TAG, "Activity exported request ignored due to singleUser: "
3602 + a.className + " at " + mArchiveSourcePath + " "
3603 + parser.getPositionDescription());
3604 a.info.exported = false;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07003605 setExported = true;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003606 }
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003607 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003608
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003609 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
3610 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07003611 false);
Dianne Hackborn7d19e022012-08-07 19:12:33 -07003612 }
3613
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003614 if (a.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07003615 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003616 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07003617 }
3618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003619 sa.recycle();
3620
Alex Klyubinb9f8a522015-02-03 11:12:59 -08003621 if (receiver && (owner.applicationInfo.privateFlags
3622 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07003623 // A heavy-weight application can not have receives in its main process
3624 // We can do direct compare because we intern all strings.
3625 if (a.info.processName == owner.packageName) {
3626 outError[0] = "Heavy-weight applications can not have receivers in main process";
3627 }
3628 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003630 if (outError[0] != null) {
3631 return null;
3632 }
3633
3634 int outerDepth = parser.getDepth();
3635 int type;
3636 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3637 && (type != XmlPullParser.END_TAG
3638 || parser.getDepth() > outerDepth)) {
3639 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3640 continue;
3641 }
3642
3643 if (parser.getName().equals("intent-filter")) {
3644 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Svet Ganov354cd3c2015-12-17 11:35:04 -08003645 if (!parseIntent(res, parser, true, true, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003646 return null;
3647 }
3648 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003649 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07003650 + mArchiveSourcePath + " "
3651 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003652 } else {
3653 a.intents.add(intent);
3654 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07003655 } else if (!receiver && parser.getName().equals("preferred")) {
3656 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Svet Ganov354cd3c2015-12-17 11:35:04 -08003657 if (!parseIntent(res, parser, false, false, intent, outError)) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07003658 return null;
3659 }
3660 if (intent.countActions() == 0) {
3661 Slog.w(TAG, "No actions in preferred at "
3662 + mArchiveSourcePath + " "
3663 + parser.getPositionDescription());
3664 } else {
3665 if (owner.preferredActivityFilters == null) {
3666 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
3667 }
3668 owner.preferredActivityFilters.add(intent);
3669 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003670 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003671 if ((a.metaData = parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003672 outError)) == null) {
3673 return null;
3674 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003675 } else if (!receiver && parser.getName().equals("layout")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003676 parseLayout(res, parser, a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003677 } else {
3678 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003679 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003680 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003681 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003682 + " at " + mArchiveSourcePath + " "
3683 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003684 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07003685 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003686 + " at " + mArchiveSourcePath + " "
3687 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003688 }
3689 XmlUtils.skipCurrentTag(parser);
3690 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003691 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07003692 if (receiver) {
3693 outError[0] = "Bad element under <receiver>: " + parser.getName();
3694 } else {
3695 outError[0] = "Bad element under <activity>: " + parser.getName();
3696 }
3697 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003698 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003699 }
3700 }
3701
3702 if (!setExported) {
3703 a.info.exported = a.intents.size() > 0;
3704 }
3705
3706 return a;
3707 }
3708
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003709 private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003710 TypedArray sw = res.obtainAttributes(attrs,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003711 com.android.internal.R.styleable.AndroidManifestLayout);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003712 int width = -1;
3713 float widthFraction = -1f;
3714 int height = -1;
3715 float heightFraction = -1f;
3716 final int widthType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003717 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003718 if (widthType == TypedValue.TYPE_FRACTION) {
3719 widthFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003720 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003721 1, 1, -1);
3722 } else if (widthType == TypedValue.TYPE_DIMENSION) {
3723 width = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003724 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003725 -1);
3726 }
3727 final int heightType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003728 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003729 if (heightType == TypedValue.TYPE_FRACTION) {
3730 heightFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003731 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003732 1, 1, -1);
3733 } else if (heightType == TypedValue.TYPE_DIMENSION) {
3734 height = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08003735 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003736 -1);
3737 }
3738 int gravity = sw.getInt(
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003739 com.android.internal.R.styleable.AndroidManifestLayout_gravity,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003740 Gravity.CENTER);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07003741 int minWidth = sw.getDimensionPixelSize(
3742 com.android.internal.R.styleable.AndroidManifestLayout_minWidth,
Andrii Kulian2e751b82016-03-16 16:59:32 -07003743 -1);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07003744 int minHeight = sw.getDimensionPixelSize(
3745 com.android.internal.R.styleable.AndroidManifestLayout_minHeight,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003746 -1);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003747 sw.recycle();
Andrii Kulian2e751b82016-03-16 16:59:32 -07003748 a.info.windowLayout = new ActivityInfo.WindowLayout(width, widthFraction,
Andrii Kulianf66a83d2016-05-17 12:17:44 -07003749 height, heightFraction, gravity, minWidth, minHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07003750 }
3751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003752 private Activity parseActivityAlias(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003753 XmlResourceParser parser, int flags, String[] outError)
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003754 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003755 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003756 com.android.internal.R.styleable.AndroidManifestActivityAlias);
3757
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003758 String targetActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003759 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
3760 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003761 if (targetActivity == null) {
3762 outError[0] = "<activity-alias> does not specify android:targetActivity";
3763 sa.recycle();
3764 return null;
3765 }
3766
3767 targetActivity = buildClassName(owner.applicationInfo.packageName,
3768 targetActivity, outError);
3769 if (targetActivity == null) {
3770 sa.recycle();
3771 return null;
3772 }
3773
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003774 if (mParseActivityAliasArgs == null) {
3775 mParseActivityAliasArgs = new ParseComponentArgs(owner, outError,
3776 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
3777 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
3778 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003779 com.android.internal.R.styleable.AndroidManifestActivityAlias_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07003780 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08003781 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003782 mSeparateProcesses,
3783 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003784 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003785 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
3786 mParseActivityAliasArgs.tag = "<activity-alias>";
3787 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003788
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003789 mParseActivityAliasArgs.sa = sa;
3790 mParseActivityAliasArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003792 Activity target = null;
3793
3794 final int NA = owner.activities.size();
3795 for (int i=0; i<NA; i++) {
3796 Activity t = owner.activities.get(i);
3797 if (targetActivity.equals(t.info.name)) {
3798 target = t;
3799 break;
3800 }
3801 }
3802
3803 if (target == null) {
3804 outError[0] = "<activity-alias> target activity " + targetActivity
3805 + " not found in manifest";
3806 sa.recycle();
3807 return null;
3808 }
3809
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003810 ActivityInfo info = new ActivityInfo();
3811 info.targetActivity = targetActivity;
3812 info.configChanges = target.info.configChanges;
3813 info.flags = target.info.flags;
3814 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07003815 info.logo = target.info.logo;
Jose Limaf78e3122014-03-06 12:13:15 -08003816 info.banner = target.info.banner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003817 info.labelRes = target.info.labelRes;
3818 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
3819 info.launchMode = target.info.launchMode;
Yao Chen597ad3f2015-06-09 16:00:14 -07003820 info.lockTaskLaunchMode = target.info.lockTaskLaunchMode;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003821 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003822 if (info.descriptionRes == 0) {
3823 info.descriptionRes = target.info.descriptionRes;
3824 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003825 info.screenOrientation = target.info.screenOrientation;
3826 info.taskAffinity = target.info.taskAffinity;
3827 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07003828 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07003829 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07003830 info.parentActivityName = target.info.parentActivityName;
Craig Mautner8307ea72014-09-11 15:03:53 -07003831 info.maxRecents = target.info.maxRecents;
Andrii Kulian2e751b82016-03-16 16:59:32 -07003832 info.windowLayout = target.info.windowLayout;
Wale Ogunwaled26176f2016-01-25 20:04:04 -08003833 info.resizeMode = target.info.resizeMode;
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003834 info.encryptionAware = info.directBootAware = target.info.directBootAware;
Craig Mautner8307ea72014-09-11 15:03:53 -07003835
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003836 Activity a = new Activity(mParseActivityAliasArgs, info);
3837 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003838 sa.recycle();
3839 return null;
3840 }
3841
3842 final boolean setExported = sa.hasValue(
3843 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
3844 if (setExported) {
3845 a.info.exported = sa.getBoolean(
3846 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
3847 }
3848
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003849 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003850 str = sa.getNonConfigurationString(
3851 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003852 if (str != null) {
3853 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
3854 }
3855
Adam Powelldd8fab22012-03-22 17:47:27 -07003856 String parentName = sa.getNonConfigurationString(
3857 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003858 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07003859 if (parentName != null) {
3860 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
3861 if (outError[0] == null) {
3862 a.info.parentActivityName = parentClassName;
3863 } else {
3864 Log.e(TAG, "Activity alias " + a.info.name +
3865 " specified invalid parentActivityName " + parentName);
3866 outError[0] = null;
3867 }
3868 }
3869
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003870 sa.recycle();
3871
3872 if (outError[0] != null) {
3873 return null;
3874 }
3875
3876 int outerDepth = parser.getDepth();
3877 int type;
3878 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
3879 && (type != XmlPullParser.END_TAG
3880 || parser.getDepth() > outerDepth)) {
3881 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3882 continue;
3883 }
3884
3885 if (parser.getName().equals("intent-filter")) {
3886 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Svet Ganov354cd3c2015-12-17 11:35:04 -08003887 if (!parseIntent(res, parser, true, true, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003888 return null;
3889 }
3890 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003891 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07003892 + mArchiveSourcePath + " "
3893 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003894 } else {
3895 a.intents.add(intent);
3896 }
3897 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003898 if ((a.metaData=parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003899 outError)) == null) {
3900 return null;
3901 }
3902 } else {
3903 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07003904 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003905 + " at " + mArchiveSourcePath + " "
3906 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003907 XmlUtils.skipCurrentTag(parser);
3908 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07003909 } else {
3910 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
3911 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003912 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003913 }
3914 }
3915
3916 if (!setExported) {
3917 a.info.exported = a.intents.size() > 0;
3918 }
3919
3920 return a;
3921 }
3922
3923 private Provider parseProvider(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003924 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003925 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003926 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003927 com.android.internal.R.styleable.AndroidManifestProvider);
3928
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003929 if (mParseProviderArgs == null) {
3930 mParseProviderArgs = new ParseComponentArgs(owner, outError,
3931 com.android.internal.R.styleable.AndroidManifestProvider_name,
3932 com.android.internal.R.styleable.AndroidManifestProvider_label,
3933 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003934 com.android.internal.R.styleable.AndroidManifestProvider_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07003935 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08003936 com.android.internal.R.styleable.AndroidManifestProvider_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003937 mSeparateProcesses,
3938 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003939 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003940 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
3941 mParseProviderArgs.tag = "<provider>";
3942 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003943
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003944 mParseProviderArgs.sa = sa;
3945 mParseProviderArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003946
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003947 Provider p = new Provider(mParseProviderArgs, new ProviderInfo());
3948 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003949 sa.recycle();
3950 return null;
3951 }
3952
Nick Kralevichf097b162012-07-28 12:43:48 -07003953 boolean providerExportedDefault = false;
3954
3955 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
3956 // For compatibility, applications targeting API level 16 or lower
3957 // should have their content providers exported by default, unless they
3958 // specify otherwise.
3959 providerExportedDefault = true;
3960 }
3961
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003962 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07003963 com.android.internal.R.styleable.AndroidManifestProvider_exported,
3964 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003965
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003966 String cpname = sa.getNonConfigurationString(
3967 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003968
3969 p.info.isSyncable = sa.getBoolean(
3970 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
3971 false);
3972
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003973 String permission = sa.getNonConfigurationString(
3974 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
3975 String str = sa.getNonConfigurationString(
3976 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003977 if (str == null) {
3978 str = permission;
3979 }
3980 if (str == null) {
3981 p.info.readPermission = owner.applicationInfo.permission;
3982 } else {
3983 p.info.readPermission =
3984 str.length() > 0 ? str.toString().intern() : null;
3985 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003986 str = sa.getNonConfigurationString(
3987 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003988 if (str == null) {
3989 str = permission;
3990 }
3991 if (str == null) {
3992 p.info.writePermission = owner.applicationInfo.permission;
3993 } else {
3994 p.info.writePermission =
3995 str.length() > 0 ? str.toString().intern() : null;
3996 }
3997
3998 p.info.grantUriPermissions = sa.getBoolean(
3999 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
4000 false);
4001
4002 p.info.multiprocess = sa.getBoolean(
4003 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
4004 false);
4005
4006 p.info.initOrder = sa.getInt(
4007 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
4008 0);
4009
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004010 p.info.flags = 0;
4011
4012 if (sa.getBoolean(
4013 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
4014 false)) {
4015 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07004016 if (p.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004017 Slog.w(TAG, "Provider exported request ignored due to singleUser: "
4018 + p.className + " at " + mArchiveSourcePath + " "
4019 + parser.getPositionDescription());
4020 p.info.exported = false;
4021 }
4022 }
4023
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004024 p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
4025 R.styleable.AndroidManifestProvider_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004026 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004027 if (p.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004028 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004029 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004030 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004032 sa.recycle();
4033
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004034 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
4035 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004036 // A heavy-weight application can not have providers in its main process
4037 // We can do direct compare because we intern all strings.
4038 if (p.info.processName == owner.packageName) {
4039 outError[0] = "Heavy-weight applications can not have providers in main process";
4040 return null;
4041 }
4042 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004044 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07004045 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004046 return null;
4047 }
Dianne Hackborn1bc177c2014-12-03 10:20:30 -08004048 if (cpname.length() <= 0) {
4049 outError[0] = "<provider> has empty authorities attribute";
4050 return null;
4051 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004052 p.info.authority = cpname.intern();
4053
Svet Ganov354cd3c2015-12-17 11:35:04 -08004054 if (!parseProviderTags(res, parser, p, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004055 return null;
4056 }
4057
4058 return p;
4059 }
4060
4061 private boolean parseProviderTags(Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08004062 XmlResourceParser parser, Provider outInfo, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004063 throws XmlPullParserException, IOException {
4064 int outerDepth = parser.getDepth();
4065 int type;
4066 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4067 && (type != XmlPullParser.END_TAG
4068 || parser.getDepth() > outerDepth)) {
4069 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4070 continue;
4071 }
4072
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004073 if (parser.getName().equals("intent-filter")) {
4074 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
Svet Ganov354cd3c2015-12-17 11:35:04 -08004075 if (!parseIntent(res, parser, true, false, intent, outError)) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004076 return false;
4077 }
4078 outInfo.intents.add(intent);
4079
4080 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004081 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004082 outInfo.metaData, outError)) == null) {
4083 return false;
4084 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004086 } else if (parser.getName().equals("grant-uri-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004087 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004088 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
4089
4090 PatternMatcher pa = null;
4091
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004092 String str = sa.getNonConfigurationString(
4093 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004094 if (str != null) {
4095 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
4096 }
4097
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004098 str = sa.getNonConfigurationString(
4099 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004100 if (str != null) {
4101 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
4102 }
4103
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004104 str = sa.getNonConfigurationString(
4105 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004106 if (str != null) {
4107 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4108 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004110 sa.recycle();
4111
4112 if (pa != null) {
4113 if (outInfo.info.uriPermissionPatterns == null) {
4114 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
4115 outInfo.info.uriPermissionPatterns[0] = pa;
4116 } else {
4117 final int N = outInfo.info.uriPermissionPatterns.length;
4118 PatternMatcher[] newp = new PatternMatcher[N+1];
4119 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
4120 newp[N] = pa;
4121 outInfo.info.uriPermissionPatterns = newp;
4122 }
4123 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004124 } else {
4125 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004126 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004127 + parser.getName() + " at " + mArchiveSourcePath + " "
4128 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004129 XmlUtils.skipCurrentTag(parser);
4130 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004131 } else {
4132 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
4133 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004134 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004135 }
4136 XmlUtils.skipCurrentTag(parser);
4137
4138 } else if (parser.getName().equals("path-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004139 TypedArray sa = res.obtainAttributes(parser,
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004140 com.android.internal.R.styleable.AndroidManifestPathPermission);
4141
4142 PathPermission pa = null;
4143
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004144 String permission = sa.getNonConfigurationString(
4145 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
4146 String readPermission = sa.getNonConfigurationString(
4147 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004148 if (readPermission == null) {
4149 readPermission = permission;
4150 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004151 String writePermission = sa.getNonConfigurationString(
4152 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004153 if (writePermission == null) {
4154 writePermission = permission;
4155 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004156
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004157 boolean havePerm = false;
4158 if (readPermission != null) {
4159 readPermission = readPermission.intern();
4160 havePerm = true;
4161 }
4162 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00004163 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004164 havePerm = true;
4165 }
4166
4167 if (!havePerm) {
4168 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004169 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004170 + parser.getName() + " at " + mArchiveSourcePath + " "
4171 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004172 XmlUtils.skipCurrentTag(parser);
4173 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004174 } else {
4175 outError[0] = "No readPermission or writePermssion for <path-permission>";
4176 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004177 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004178 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004179
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004180 String path = sa.getNonConfigurationString(
4181 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004182 if (path != null) {
4183 pa = new PathPermission(path,
4184 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
4185 }
4186
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004187 path = sa.getNonConfigurationString(
4188 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004189 if (path != null) {
4190 pa = new PathPermission(path,
4191 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
4192 }
4193
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004194 path = sa.getNonConfigurationString(
4195 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004196 if (path != null) {
4197 pa = new PathPermission(path,
4198 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
4199 }
4200
4201 sa.recycle();
4202
4203 if (pa != null) {
4204 if (outInfo.info.pathPermissions == null) {
4205 outInfo.info.pathPermissions = new PathPermission[1];
4206 outInfo.info.pathPermissions[0] = pa;
4207 } else {
4208 final int N = outInfo.info.pathPermissions.length;
4209 PathPermission[] newp = new PathPermission[N+1];
4210 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
4211 newp[N] = pa;
4212 outInfo.info.pathPermissions = newp;
4213 }
4214 } else {
4215 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004216 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004217 + parser.getName() + " at " + mArchiveSourcePath + " "
4218 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004219 XmlUtils.skipCurrentTag(parser);
4220 continue;
4221 }
4222 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
4223 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004224 }
4225 XmlUtils.skipCurrentTag(parser);
4226
4227 } else {
4228 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004229 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004230 + parser.getName() + " at " + mArchiveSourcePath + " "
4231 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004232 XmlUtils.skipCurrentTag(parser);
4233 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004234 } else {
4235 outError[0] = "Bad element under <provider>: " + parser.getName();
4236 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004237 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004238 }
4239 }
4240 return true;
4241 }
4242
4243 private Service parseService(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08004244 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004245 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004246 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004247 com.android.internal.R.styleable.AndroidManifestService);
4248
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004249 if (mParseServiceArgs == null) {
4250 mParseServiceArgs = new ParseComponentArgs(owner, outError,
4251 com.android.internal.R.styleable.AndroidManifestService_name,
4252 com.android.internal.R.styleable.AndroidManifestService_label,
4253 com.android.internal.R.styleable.AndroidManifestService_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004254 com.android.internal.R.styleable.AndroidManifestService_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004255 com.android.internal.R.styleable.AndroidManifestService_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004256 com.android.internal.R.styleable.AndroidManifestService_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004257 mSeparateProcesses,
4258 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004259 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004260 com.android.internal.R.styleable.AndroidManifestService_enabled);
4261 mParseServiceArgs.tag = "<service>";
4262 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004263
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004264 mParseServiceArgs.sa = sa;
4265 mParseServiceArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004266
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004267 Service s = new Service(mParseServiceArgs, new ServiceInfo());
4268 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004269 sa.recycle();
4270 return null;
4271 }
4272
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004273 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004274 com.android.internal.R.styleable.AndroidManifestService_exported);
4275 if (setExported) {
4276 s.info.exported = sa.getBoolean(
4277 com.android.internal.R.styleable.AndroidManifestService_exported, false);
4278 }
4279
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004280 String str = sa.getNonConfigurationString(
4281 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004282 if (str == null) {
4283 s.info.permission = owner.applicationInfo.permission;
4284 } else {
4285 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
4286 }
4287
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004288 s.info.flags = 0;
4289 if (sa.getBoolean(
4290 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
4291 false)) {
4292 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
4293 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08004294 if (sa.getBoolean(
4295 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
4296 false)) {
4297 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
4298 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004299 if (sa.getBoolean(
Robert Sesekb9a86662015-12-09 16:22:45 -05004300 com.android.internal.R.styleable.AndroidManifestService_externalService,
4301 false)) {
4302 s.info.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE;
4303 }
4304 if (sa.getBoolean(
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004305 com.android.internal.R.styleable.AndroidManifestService_singleUser,
4306 false)) {
4307 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07004308 if (s.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004309 Slog.w(TAG, "Service exported request ignored due to singleUser: "
4310 + s.className + " at " + mArchiveSourcePath + " "
4311 + parser.getPositionDescription());
4312 s.info.exported = false;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07004313 setExported = true;
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004314 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07004315 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07004316
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004317 s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
4318 R.styleable.AndroidManifestService_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004319 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004320 if (s.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004321 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004322 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004323 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004325 sa.recycle();
4326
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004327 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
4328 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004329 // A heavy-weight application can not have services in its main process
4330 // We can do direct compare because we intern all strings.
4331 if (s.info.processName == owner.packageName) {
4332 outError[0] = "Heavy-weight applications can not have services in main process";
4333 return null;
4334 }
4335 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004336
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004337 int outerDepth = parser.getDepth();
4338 int type;
4339 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4340 && (type != XmlPullParser.END_TAG
4341 || parser.getDepth() > outerDepth)) {
4342 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4343 continue;
4344 }
4345
4346 if (parser.getName().equals("intent-filter")) {
4347 ServiceIntentInfo intent = new ServiceIntentInfo(s);
Svet Ganov354cd3c2015-12-17 11:35:04 -08004348 if (!parseIntent(res, parser, true, false, intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004349 return null;
4350 }
4351
4352 s.intents.add(intent);
4353 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004354 if ((s.metaData=parseMetaData(res, parser, s.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004355 outError)) == null) {
4356 return null;
4357 }
4358 } else {
4359 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004360 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004361 + parser.getName() + " at " + mArchiveSourcePath + " "
4362 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004363 XmlUtils.skipCurrentTag(parser);
4364 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004365 } else {
4366 outError[0] = "Bad element under <service>: " + parser.getName();
4367 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004369 }
4370 }
4371
4372 if (!setExported) {
4373 s.info.exported = s.intents.size() > 0;
4374 }
4375
4376 return s;
4377 }
4378
Svet Ganov354cd3c2015-12-17 11:35:04 -08004379 private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag,
4380 Component<?> outInfo, String[] outError) throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004381 int outerDepth = parser.getDepth();
4382 int type;
4383 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4384 && (type != XmlPullParser.END_TAG
4385 || parser.getDepth() > outerDepth)) {
4386 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4387 continue;
4388 }
4389
4390 if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004391 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004392 outInfo.metaData, outError)) == null) {
4393 return false;
4394 }
4395 } else {
4396 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004397 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004398 + parser.getName() + " at " + mArchiveSourcePath + " "
4399 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004400 XmlUtils.skipCurrentTag(parser);
4401 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004402 } else {
4403 outError[0] = "Bad element under " + tag + ": " + parser.getName();
4404 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004405 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004406 }
4407 }
4408 return true;
4409 }
4410
4411 private Bundle parseMetaData(Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08004412 XmlResourceParser parser, Bundle data, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004413 throws XmlPullParserException, IOException {
4414
Svet Ganov354cd3c2015-12-17 11:35:04 -08004415 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004416 com.android.internal.R.styleable.AndroidManifestMetaData);
4417
4418 if (data == null) {
4419 data = new Bundle();
4420 }
4421
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004422 String name = sa.getNonConfigurationString(
4423 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004424 if (name == null) {
4425 outError[0] = "<meta-data> requires an android:name attribute";
4426 sa.recycle();
4427 return null;
4428 }
4429
Dianne Hackborn854060af2009-07-09 18:14:31 -07004430 name = name.intern();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004431
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004432 TypedValue v = sa.peekValue(
4433 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
4434 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004435 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 data.putInt(name, v.resourceId);
4437 } else {
4438 v = sa.peekValue(
4439 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07004440 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004441 if (v != null) {
4442 if (v.type == TypedValue.TYPE_STRING) {
4443 CharSequence cs = v.coerceToString();
Dianne Hackborn854060af2009-07-09 18:14:31 -07004444 data.putString(name, cs != null ? cs.toString().intern() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004445 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
4446 data.putBoolean(name, v.data != 0);
4447 } else if (v.type >= TypedValue.TYPE_FIRST_INT
4448 && v.type <= TypedValue.TYPE_LAST_INT) {
4449 data.putInt(name, v.data);
4450 } else if (v.type == TypedValue.TYPE_FLOAT) {
4451 data.putFloat(name, v.getFloat());
4452 } else {
4453 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004454 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004455 + parser.getName() + " at " + mArchiveSourcePath + " "
4456 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004457 } else {
4458 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
4459 data = null;
4460 }
4461 }
4462 } else {
4463 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
4464 data = null;
4465 }
4466 }
4467
4468 sa.recycle();
4469
4470 XmlUtils.skipCurrentTag(parser);
4471
4472 return data;
4473 }
4474
Kenny Root05ca4c92011-09-15 10:36:25 -07004475 private static VerifierInfo parseVerifier(Resources res, XmlPullParser parser,
Jeff Sharkey275e0852014-06-17 18:18:49 -07004476 AttributeSet attrs, int flags) {
Kenny Root05ca4c92011-09-15 10:36:25 -07004477 final TypedArray sa = res.obtainAttributes(attrs,
4478 com.android.internal.R.styleable.AndroidManifestPackageVerifier);
4479
4480 final String packageName = sa.getNonResourceString(
4481 com.android.internal.R.styleable.AndroidManifestPackageVerifier_name);
4482
4483 final String encodedPublicKey = sa.getNonResourceString(
4484 com.android.internal.R.styleable.AndroidManifestPackageVerifier_publicKey);
4485
4486 sa.recycle();
4487
4488 if (packageName == null || packageName.length() == 0) {
4489 Slog.i(TAG, "verifier package name was null; skipping");
4490 return null;
Kenny Root05ca4c92011-09-15 10:36:25 -07004491 }
4492
Christopher Tate30147332014-04-15 12:57:47 -07004493 final PublicKey publicKey = parsePublicKey(encodedPublicKey);
4494 if (publicKey == null) {
4495 Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
4496 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -08004497 }
4498
Christopher Tate30147332014-04-15 12:57:47 -07004499 return new VerifierInfo(packageName, publicKey);
Geremy Condraf1bcca82013-01-07 22:35:24 -08004500 }
4501
Christopher Tate30147332014-04-15 12:57:47 -07004502 public static final PublicKey parsePublicKey(final String encodedPublicKey) {
4503 if (encodedPublicKey == null) {
dcashman1616f302015-05-29 14:47:23 -07004504 Slog.w(TAG, "Could not parse null public key");
Christopher Tate30147332014-04-15 12:57:47 -07004505 return null;
4506 }
4507
Kenny Root05ca4c92011-09-15 10:36:25 -07004508 EncodedKeySpec keySpec;
4509 try {
4510 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
4511 keySpec = new X509EncodedKeySpec(encoded);
4512 } catch (IllegalArgumentException e) {
dcashman1616f302015-05-29 14:47:23 -07004513 Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07004514 return null;
4515 }
4516
4517 /* First try the key as an RSA key. */
4518 try {
4519 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08004520 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07004521 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07004522 Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07004523 } catch (InvalidKeySpecException e) {
4524 // Not a RSA public key.
4525 }
4526
dcashman1616f302015-05-29 14:47:23 -07004527 /* Now try it as a ECDSA key. */
4528 try {
4529 final KeyFactory keyFactory = KeyFactory.getInstance("EC");
4530 return keyFactory.generatePublic(keySpec);
4531 } catch (NoSuchAlgorithmException e) {
4532 Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build");
4533 } catch (InvalidKeySpecException e) {
4534 // Not a ECDSA public key.
4535 }
4536
Kenny Root05ca4c92011-09-15 10:36:25 -07004537 /* Now try it as a DSA key. */
4538 try {
4539 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08004540 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07004541 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07004542 Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07004543 } catch (InvalidKeySpecException e) {
4544 // Not a DSA public key.
4545 }
4546
dcashman1616f302015-05-29 14:47:23 -07004547 /* Not a supported key type */
Kenny Root05ca4c92011-09-15 10:36:25 -07004548 return null;
4549 }
4550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004551 private static final String ANDROID_RESOURCES
4552 = "http://schemas.android.com/apk/res/android";
4553
Svet Ganov354cd3c2015-12-17 11:35:04 -08004554 private boolean parseIntent(Resources res, XmlResourceParser parser,
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08004555 boolean allowGlobs, boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004556 throws XmlPullParserException, IOException {
4557
Svet Ganov354cd3c2015-12-17 11:35:04 -08004558 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004559 com.android.internal.R.styleable.AndroidManifestIntentFilter);
4560
4561 int priority = sa.getInt(
4562 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004563 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08004564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004565 TypedValue v = sa.peekValue(
4566 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
4567 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4568 outInfo.nonLocalizedLabel = v.coerceToString();
4569 }
4570
Todd Kennedya83bfca2016-06-03 07:52:17 -07004571 final boolean useRoundIcon =
4572 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
4573 int roundIconVal = useRoundIcon ? sa.getResourceId(
4574 com.android.internal.R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0;
4575 if (roundIconVal != 0) {
4576 outInfo.icon = roundIconVal;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004577 } else {
4578 outInfo.icon = sa.getResourceId(
4579 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
4580 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004581
Adam Powell81cd2e92010-04-21 16:35:18 -07004582 outInfo.logo = sa.getResourceId(
4583 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004584
Jose Limaf78e3122014-03-06 12:13:15 -08004585 outInfo.banner = sa.getResourceId(
4586 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
4587
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08004588 if (allowAutoVerify) {
4589 outInfo.setAutoVerify(sa.getBoolean(
4590 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
4591 false));
4592 }
4593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004594 sa.recycle();
4595
4596 int outerDepth = parser.getDepth();
4597 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07004598 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
4599 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
4600 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004601 continue;
4602 }
4603
4604 String nodeName = parser.getName();
4605 if (nodeName.equals("action")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004606 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004607 ANDROID_RESOURCES, "name");
4608 if (value == null || value == "") {
4609 outError[0] = "No value supplied for <android:name>";
4610 return false;
4611 }
4612 XmlUtils.skipCurrentTag(parser);
4613
4614 outInfo.addAction(value);
4615 } else if (nodeName.equals("category")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004616 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004617 ANDROID_RESOURCES, "name");
4618 if (value == null || value == "") {
4619 outError[0] = "No value supplied for <android:name>";
4620 return false;
4621 }
4622 XmlUtils.skipCurrentTag(parser);
4623
4624 outInfo.addCategory(value);
4625
4626 } else if (nodeName.equals("data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004627 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004628 com.android.internal.R.styleable.AndroidManifestData);
4629
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004630 String str = sa.getNonConfigurationString(
4631 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004632 if (str != null) {
4633 try {
4634 outInfo.addDataType(str);
4635 } catch (IntentFilter.MalformedMimeTypeException e) {
4636 outError[0] = e.toString();
4637 sa.recycle();
4638 return false;
4639 }
4640 }
4641
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004642 str = sa.getNonConfigurationString(
4643 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004644 if (str != null) {
4645 outInfo.addDataScheme(str);
4646 }
4647
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07004648 str = sa.getNonConfigurationString(
4649 com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
4650 if (str != null) {
4651 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
4652 }
4653
4654 str = sa.getNonConfigurationString(
4655 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
4656 if (str != null) {
4657 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
4658 }
4659
4660 str = sa.getNonConfigurationString(
4661 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
4662 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004663 if (!allowGlobs) {
4664 outError[0] = "sspPattern not allowed here; ssp must be literal";
4665 return false;
4666 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07004667 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4668 }
4669
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004670 String host = sa.getNonConfigurationString(
4671 com.android.internal.R.styleable.AndroidManifestData_host, 0);
4672 String port = sa.getNonConfigurationString(
4673 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004674 if (host != null) {
4675 outInfo.addDataAuthority(host, port);
4676 }
4677
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004678 str = sa.getNonConfigurationString(
4679 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004680 if (str != null) {
4681 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
4682 }
4683
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004684 str = sa.getNonConfigurationString(
4685 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004686 if (str != null) {
4687 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
4688 }
4689
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004690 str = sa.getNonConfigurationString(
4691 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004692 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004693 if (!allowGlobs) {
4694 outError[0] = "pathPattern not allowed here; path must be literal";
4695 return false;
4696 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004697 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
4698 }
4699
4700 sa.recycle();
4701 XmlUtils.skipCurrentTag(parser);
4702 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004703 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004704 + parser.getName() + " at " + mArchiveSourcePath + " "
4705 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004706 XmlUtils.skipCurrentTag(parser);
4707 } else {
4708 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
4709 return false;
4710 }
4711 }
4712
4713 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07004714
4715 if (DEBUG_PARSER) {
4716 final StringBuilder cats = new StringBuilder("Intent d=");
4717 cats.append(outInfo.hasDefault);
4718 cats.append(", cat=");
4719
4720 final Iterator<String> it = outInfo.categoriesIterator();
4721 if (it != null) {
4722 while (it.hasNext()) {
4723 cats.append(' ');
4724 cats.append(it.next());
4725 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004726 }
Kenny Rootd2d29252011-08-08 11:27:57 -07004727 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004728 }
4729
4730 return true;
4731 }
4732
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004733 /**
4734 * Representation of a full package parsed from APK files on disk. A package
4735 * consists of a single base APK, and zero or more split APKs.
4736 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004737 public final static class Package {
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07004738
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004739 public String packageName;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004740
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004741 /** Names of any split APKs, ordered by parsed splitName */
4742 public String[] splitNames;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004743
4744 // TODO: work towards making these paths invariant
Jeff Sharkey275e0852014-06-17 18:18:49 -07004745
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07004746 public String volumeUuid;
4747
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004748 /**
4749 * Path where this package was found on disk. For monolithic packages
4750 * this is path to single base APK file; for cluster packages this is
4751 * path to the cluster directory.
4752 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004753 public String codePath;
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07004754
4755 /** Path of base APK */
4756 public String baseCodePath;
4757 /** Paths of any split APKs, ordered by parsed splitName */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004758 public String[] splitCodePaths;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004759
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004760 /** Revision code of base APK */
4761 public int baseRevisionCode;
4762 /** Revision codes of any split APKs, ordered by parsed splitName */
4763 public int[] splitRevisionCodes;
4764
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004765 /** Flags of any split APKs; ordered by parsed splitName */
4766 public int[] splitFlags;
4767
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004768 /**
4769 * Private flags of any split APKs; ordered by parsed splitName.
4770 *
4771 * {@hide}
4772 */
4773 public int[] splitPrivateFlags;
4774
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004775 public boolean baseHardwareAccelerated;
4776
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004777 // For now we only support one application per package.
4778 public final ApplicationInfo applicationInfo = new ApplicationInfo();
4779
4780 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
4781 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
4782 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
4783 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
4784 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
4785 public final ArrayList<Service> services = new ArrayList<Service>(0);
4786 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
4787
4788 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
4789
Dianne Hackborn854060af2009-07-09 18:14:31 -07004790 public ArrayList<String> protectedBroadcasts;
Dianne Hackbornc895be72013-03-11 17:48:43 -07004791
Svet Ganov354cd3c2015-12-17 11:35:04 -08004792 public Package parentPackage;
4793 public ArrayList<Package> childPackages;
4794
Dianne Hackbornc895be72013-03-11 17:48:43 -07004795 public ArrayList<String> libraryNames = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07004796 public ArrayList<String> usesLibraries = null;
4797 public ArrayList<String> usesOptionalLibraries = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004798 public String[] usesLibraryFiles = null;
4799
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004800 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
4801
Dianne Hackbornc1552392010-03-03 16:19:01 -08004802 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004803 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08004804 public ArrayList<String> mAdoptPermissions = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004806 // We store the application meta-data independently to avoid multiple unwanted references
4807 public Bundle mAppMetaData = null;
4808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004809 // The version code declared for this package.
4810 public int mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08004811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004812 // The version name declared for this package.
4813 public String mVersionName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815 // The shared user id that this package wants to use.
4816 public String mSharedUserId;
4817
4818 // The shared user label that this package wants to use.
4819 public int mSharedUserLabel;
4820
4821 // Signatures that were read from the package.
Jeff Sharkey275e0852014-06-17 18:18:49 -07004822 public Signature[] mSignatures;
4823 public Certificate[][] mCertificates;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004824
4825 // For use by package manager service for quick lookup of
4826 // preferred up order.
4827 public int mPreferredOrder = 0;
4828
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07004829 // For use by package manager to keep track of when a package was last used.
Brian Carlstromca82e612016-04-19 23:16:08 -07004830 public long[] mLastPackageUsageTimeInMills =
4831 new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07004832
Amith Yamasani13593602012-03-22 16:16:17 -07004833 // // User set enabled state.
4834 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
4835 //
4836 // // Whether the package has been stopped.
4837 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004839 // Additional data supplied by callers.
4840 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07004841
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004842 // Applications hardware preferences
4843 public ArrayList<ConfigurationInfo> configPreferences = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004844
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004845 // Applications requested features
Dianne Hackborn49237342009-08-27 20:08:01 -07004846 public ArrayList<FeatureInfo> reqFeatures = null;
4847
Adam Lesinskid3edfde2014-08-08 17:32:44 -07004848 // Applications requested feature groups
4849 public ArrayList<FeatureGroupInfo> featureGroups = null;
4850
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08004851 public int installLocation;
4852
Jeff Hao272bf3a2014-10-08 13:34:43 -07004853 public boolean coreApp;
4854
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08004855 /* An app that's required for all users and cannot be uninstalled for a user */
4856 public boolean mRequiredForAllUsers;
4857
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07004858 /* The restricted account authenticator type that is used by this application */
4859 public String mRestrictedAccountType;
4860
Amith Yamasaniccbe3892013-04-12 17:52:42 -07004861 /* The required account type without which this application will not function */
4862 public String mRequiredAccountType;
4863
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01004864 public String mOverlayTarget;
4865 public int mOverlayPriority;
4866 public boolean mTrustedOverlay;
4867
Geremy Condraf1bcca82013-01-07 22:35:24 -08004868 /**
dcashman989eb3712014-06-17 12:56:12 -07004869 * Data used to feed the KeySetManagerService
Geremy Condraf1bcca82013-01-07 22:35:24 -08004870 */
dcashman989eb3712014-06-17 12:56:12 -07004871 public ArraySet<PublicKey> mSigningKeys;
4872 public ArraySet<String> mUpgradeKeySets;
4873 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -08004874
Narayan Kamath4903f642014-08-11 13:33:45 +01004875 /**
4876 * The install time abi override for this package, if any.
4877 *
4878 * TODO: This seems like a horrible place to put the abiOverride because
4879 * this isn't something the packageParser parsers. However, this fits in with
4880 * the rest of the PackageManager where package scanning randomly pushes
4881 * and prods fields out of {@code this.applicationInfo}.
4882 */
4883 public String cpuAbiOverride;
Selim Gurun2d291d82016-02-05 17:50:53 -08004884 /**
4885 * The install time abi override to choose 32bit abi's when multiple abi's
4886 * are present. This is only meaningfull for multiarch applications.
4887 * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
4888 */
4889 public boolean use32bitAbi;
Narayan Kamath4903f642014-08-11 13:33:45 +01004890
Todd Kennedyfdd241a2016-04-28 12:26:53 -07004891 public byte[] restrictUpdateHash;
4892
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07004893 public Package(String packageName) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07004894 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07004895 applicationInfo.packageName = packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004896 applicationInfo.uid = -1;
4897 }
4898
Svet Ganov354cd3c2015-12-17 11:35:04 -08004899 public void setApplicationVolumeUuid(String volumeUuid) {
4900 this.applicationInfo.volumeUuid = volumeUuid;
4901 if (childPackages != null) {
4902 final int packageCount = childPackages.size();
4903 for (int i = 0; i < packageCount; i++) {
4904 childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
4905 }
4906 }
4907 }
4908
4909 public void setApplicationInfoCodePath(String codePath) {
4910 this.applicationInfo.setCodePath(codePath);
4911 if (childPackages != null) {
4912 final int packageCount = childPackages.size();
4913 for (int i = 0; i < packageCount; i++) {
4914 childPackages.get(i).applicationInfo.setCodePath(codePath);
4915 }
4916 }
4917 }
4918
4919 public void setApplicationInfoResourcePath(String resourcePath) {
4920 this.applicationInfo.setResourcePath(resourcePath);
4921 if (childPackages != null) {
4922 final int packageCount = childPackages.size();
4923 for (int i = 0; i < packageCount; i++) {
4924 childPackages.get(i).applicationInfo.setResourcePath(resourcePath);
4925 }
4926 }
4927 }
4928
4929 public void setApplicationInfoBaseResourcePath(String resourcePath) {
4930 this.applicationInfo.setBaseResourcePath(resourcePath);
4931 if (childPackages != null) {
4932 final int packageCount = childPackages.size();
4933 for (int i = 0; i < packageCount; i++) {
4934 childPackages.get(i).applicationInfo.setBaseResourcePath(resourcePath);
4935 }
4936 }
4937 }
4938
4939 public void setApplicationInfoBaseCodePath(String baseCodePath) {
4940 this.applicationInfo.setBaseCodePath(baseCodePath);
4941 if (childPackages != null) {
4942 final int packageCount = childPackages.size();
4943 for (int i = 0; i < packageCount; i++) {
4944 childPackages.get(i).applicationInfo.setBaseCodePath(baseCodePath);
4945 }
4946 }
4947 }
4948
4949 public boolean hasChildPackage(String packageName) {
4950 final int childCount = (childPackages != null) ? childPackages.size() : 0;
4951 for (int i = 0; i < childCount; i++) {
4952 if (childPackages.get(i).packageName.equals(packageName)) {
4953 return true;
4954 }
4955 }
4956 return false;
4957 }
4958
4959 public void setApplicationInfoSplitCodePaths(String[] splitCodePaths) {
4960 this.applicationInfo.setSplitCodePaths(splitCodePaths);
4961 // Children have no splits
4962 }
4963
4964 public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) {
4965 this.applicationInfo.setSplitResourcePaths(resroucePaths);
4966 // Children have no splits
4967 }
4968
4969 public void setSplitCodePaths(String[] codePaths) {
4970 this.splitCodePaths = codePaths;
4971 }
4972
4973 public void setCodePath(String codePath) {
4974 this.codePath = codePath;
4975 if (childPackages != null) {
4976 final int packageCount = childPackages.size();
4977 for (int i = 0; i < packageCount; i++) {
4978 childPackages.get(i).codePath = codePath;
4979 }
4980 }
4981 }
4982
4983 public void setBaseCodePath(String baseCodePath) {
4984 this.baseCodePath = baseCodePath;
4985 if (childPackages != null) {
4986 final int packageCount = childPackages.size();
4987 for (int i = 0; i < packageCount; i++) {
4988 childPackages.get(i).baseCodePath = baseCodePath;
4989 }
4990 }
4991 }
4992
4993 public void setSignatures(Signature[] signatures) {
4994 this.mSignatures = signatures;
4995 if (childPackages != null) {
4996 final int packageCount = childPackages.size();
4997 for (int i = 0; i < packageCount; i++) {
4998 childPackages.get(i).mSignatures = signatures;
4999 }
5000 }
5001 }
5002
5003 public void setVolumeUuid(String volumeUuid) {
5004 this.volumeUuid = volumeUuid;
5005 if (childPackages != null) {
5006 final int packageCount = childPackages.size();
5007 for (int i = 0; i < packageCount; i++) {
5008 childPackages.get(i).volumeUuid = volumeUuid;
5009 }
5010 }
5011 }
5012
5013 public void setApplicationInfoFlags(int mask, int flags) {
5014 applicationInfo.flags = (applicationInfo.flags & ~mask) | (mask & flags);
5015 if (childPackages != null) {
5016 final int packageCount = childPackages.size();
5017 for (int i = 0; i < packageCount; i++) {
5018 childPackages.get(i).applicationInfo.flags =
5019 (applicationInfo.flags & ~mask) | (mask & flags);
5020 }
5021 }
5022 }
5023
Selim Gurun75827b22016-02-09 10:55:33 -08005024 public void setUse32bitAbi(boolean use32bitAbi) {
Selim Gurun2d291d82016-02-05 17:50:53 -08005025 this.use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08005026 if (childPackages != null) {
5027 final int packageCount = childPackages.size();
5028 for (int i = 0; i < packageCount; i++) {
Selim Gurun2d291d82016-02-05 17:50:53 -08005029 childPackages.get(i).use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08005030 }
5031 }
5032 }
5033
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005034 public List<String> getAllCodePaths() {
Jeff Sharkey275e0852014-06-17 18:18:49 -07005035 ArrayList<String> paths = new ArrayList<>();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005036 paths.add(baseCodePath);
Jeff Sharkey275e0852014-06-17 18:18:49 -07005037 if (!ArrayUtils.isEmpty(splitCodePaths)) {
5038 Collections.addAll(paths, splitCodePaths);
5039 }
5040 return paths;
5041 }
5042
Jeff Sharkeyda96e132014-07-15 14:54:09 -07005043 /**
5044 * Filtered set of {@link #getAllCodePaths()} that excludes
5045 * resource-only APKs.
5046 */
5047 public List<String> getAllCodePathsExcludingResourceOnly() {
5048 ArrayList<String> paths = new ArrayList<>();
5049 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
5050 paths.add(baseCodePath);
5051 }
5052 if (!ArrayUtils.isEmpty(splitCodePaths)) {
5053 for (int i = 0; i < splitCodePaths.length; i++) {
5054 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
5055 paths.add(splitCodePaths[i]);
5056 }
5057 }
5058 }
5059 return paths;
5060 }
5061
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005062 public void setPackageName(String newName) {
5063 packageName = newName;
5064 applicationInfo.packageName = newName;
5065 for (int i=permissions.size()-1; i>=0; i--) {
5066 permissions.get(i).setPackageName(newName);
5067 }
5068 for (int i=permissionGroups.size()-1; i>=0; i--) {
5069 permissionGroups.get(i).setPackageName(newName);
5070 }
5071 for (int i=activities.size()-1; i>=0; i--) {
5072 activities.get(i).setPackageName(newName);
5073 }
5074 for (int i=receivers.size()-1; i>=0; i--) {
5075 receivers.get(i).setPackageName(newName);
5076 }
5077 for (int i=providers.size()-1; i>=0; i--) {
5078 providers.get(i).setPackageName(newName);
5079 }
5080 for (int i=services.size()-1; i>=0; i--) {
5081 services.get(i).setPackageName(newName);
5082 }
5083 for (int i=instrumentation.size()-1; i>=0; i--) {
5084 instrumentation.get(i).setPackageName(newName);
5085 }
5086 }
Dianne Hackborn65696252012-03-05 18:49:21 -08005087
5088 public boolean hasComponentClassName(String name) {
5089 for (int i=activities.size()-1; i>=0; i--) {
5090 if (name.equals(activities.get(i).className)) {
5091 return true;
5092 }
5093 }
5094 for (int i=receivers.size()-1; i>=0; i--) {
5095 if (name.equals(receivers.get(i).className)) {
5096 return true;
5097 }
5098 }
5099 for (int i=providers.size()-1; i>=0; i--) {
5100 if (name.equals(providers.get(i).className)) {
5101 return true;
5102 }
5103 }
5104 for (int i=services.size()-1; i>=0; i--) {
5105 if (name.equals(services.get(i).className)) {
5106 return true;
5107 }
5108 }
5109 for (int i=instrumentation.size()-1; i>=0; i--) {
5110 if (name.equals(instrumentation.get(i).className)) {
5111 return true;
5112 }
5113 }
5114 return false;
5115 }
5116
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08005117 /**
5118 * @hide
5119 */
5120 public boolean isForwardLocked() {
5121 return applicationInfo.isForwardLocked();
5122 }
5123
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08005124 /**
5125 * @hide
5126 */
5127 public boolean isSystemApp() {
5128 return applicationInfo.isSystemApp();
5129 }
5130
5131 /**
5132 * @hide
5133 */
Svet Ganovadc1cf42015-06-15 16:36:24 -07005134 public boolean isPrivilegedApp() {
5135 return applicationInfo.isPrivilegedApp();
5136 }
5137
5138 /**
5139 * @hide
5140 */
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08005141 public boolean isUpdatedSystemApp() {
5142 return applicationInfo.isUpdatedSystemApp();
5143 }
5144
Fyodor Kupolovebcac162015-09-09 15:56:45 -07005145 /**
5146 * @hide
5147 */
5148 public boolean canHaveOatDir() {
5149 // The following app types CANNOT have oat directory
5150 // - non-updated system apps
5151 // - forward-locked apps or apps installed in ASEC containers
5152 return (!isSystemApp() || isUpdatedSystemApp())
5153 && !isForwardLocked() && !applicationInfo.isExternalAsec();
5154 }
5155
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07005156 public boolean isMatch(int flags) {
5157 if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
5158 return isSystemApp();
5159 }
5160 return true;
5161 }
5162
Brian Carlstromca82e612016-04-19 23:16:08 -07005163 public long getLatestPackageUseTimeInMills() {
5164 long latestUse = 0L;
5165 for (long use : mLastPackageUsageTimeInMills) {
5166 latestUse = Math.max(latestUse, use);
5167 }
5168 return latestUse;
5169 }
5170
David Brazdil90e26992016-04-18 14:08:52 +01005171 public long getLatestForegroundPackageUseTimeInMills() {
5172 int[] foregroundReasons = {
5173 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
5174 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
5175 };
5176
5177 long latestUse = 0L;
5178 for (int reason : foregroundReasons) {
5179 latestUse = Math.max(latestUse, mLastPackageUsageTimeInMills[reason]);
5180 }
5181 return latestUse;
5182 }
5183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005184 public String toString() {
5185 return "Package{"
5186 + Integer.toHexString(System.identityHashCode(this))
5187 + " " + packageName + "}";
5188 }
5189 }
5190
5191 public static class Component<II extends IntentInfo> {
5192 public final Package owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005193 public final ArrayList<II> intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005194 public final String className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195 public Bundle metaData;
5196
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005197 ComponentName componentName;
5198 String componentShortName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005200 public Component(Package _owner) {
5201 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005202 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005203 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005204 }
5205
5206 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
5207 owner = args.owner;
5208 intents = new ArrayList<II>(0);
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005209 if (parsePackageItemInfo(args.owner, outInfo, args.outError, args.tag, args.sa,
5210 true /*nameRequired*/, args.nameRes, args.labelRes, args.iconRes,
5211 args.roundIconRes, args.logoRes, args.bannerRes)) {
5212 className = outInfo.name;
5213 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005214 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005215 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005216 }
5217
5218 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
5219 this(args, (PackageItemInfo)outInfo);
5220 if (args.outError[0] != null) {
5221 return;
5222 }
5223
5224 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07005225 CharSequence pname;
5226 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07005227 pname = args.sa.getNonConfigurationString(args.processRes,
5228 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07005229 } else {
5230 // Some older apps have been seen to use a resource reference
5231 // here that on older builds was ignored (with a warning). We
5232 // need to continue to do this for them so they don't break.
5233 pname = args.sa.getNonResourceString(args.processRes);
5234 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005235 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07005236 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005237 args.flags, args.sepProcesses, args.outError);
5238 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005239
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005240 if (args.descriptionRes != 0) {
5241 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
5242 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005243
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005244 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005245 }
5246
5247 public Component(Component<II> clone) {
5248 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005249 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005250 className = clone.className;
5251 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005252 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005253 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005254
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005255 public ComponentName getComponentName() {
5256 if (componentName != null) {
5257 return componentName;
5258 }
5259 if (className != null) {
5260 componentName = new ComponentName(owner.applicationInfo.packageName,
5261 className);
5262 }
5263 return componentName;
5264 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005265
5266 public void appendComponentShortName(StringBuilder sb) {
5267 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005268 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005269
5270 public void printComponentShortName(PrintWriter pw) {
5271 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
5272 }
5273
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005274 public void setPackageName(String packageName) {
5275 componentName = null;
5276 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005277 }
5278 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005280 public final static class Permission extends Component<IntentInfo> {
5281 public final PermissionInfo info;
5282 public boolean tree;
5283 public PermissionGroup group;
5284
5285 public Permission(Package _owner) {
5286 super(_owner);
5287 info = new PermissionInfo();
5288 }
5289
5290 public Permission(Package _owner, PermissionInfo _info) {
5291 super(_owner);
5292 info = _info;
5293 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005294
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005295 public void setPackageName(String packageName) {
5296 super.setPackageName(packageName);
5297 info.packageName = packageName;
5298 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005299
5300 public String toString() {
5301 return "Permission{"
5302 + Integer.toHexString(System.identityHashCode(this))
5303 + " " + info.name + "}";
5304 }
5305 }
5306
5307 public final static class PermissionGroup extends Component<IntentInfo> {
5308 public final PermissionGroupInfo info;
5309
5310 public PermissionGroup(Package _owner) {
5311 super(_owner);
5312 info = new PermissionGroupInfo();
5313 }
5314
5315 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
5316 super(_owner);
5317 info = _info;
5318 }
5319
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005320 public void setPackageName(String packageName) {
5321 super.setPackageName(packageName);
5322 info.packageName = packageName;
5323 }
5324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005325 public String toString() {
5326 return "PermissionGroup{"
5327 + Integer.toHexString(System.identityHashCode(this))
5328 + " " + info.name + "}";
5329 }
5330 }
5331
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005332 private static boolean copyNeeded(int flags, Package p,
5333 PackageUserState state, Bundle metaData, int userId) {
Xiaohui Chen98404fd2015-08-17 16:09:02 -07005334 if (userId != UserHandle.USER_SYSTEM) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005335 // We always need to copy for other users, since we need
5336 // to fix up the uid.
5337 return true;
5338 }
5339 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
5340 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07005341 if (p.applicationInfo.enabled != enabled) {
5342 return true;
5343 }
5344 }
Rubin Xubf67c9c2016-04-20 17:09:38 +01005345 boolean suspended = (p.applicationInfo.flags & FLAG_SUSPENDED) != 0;
5346 if (state.suspended != suspended) {
5347 return true;
5348 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07005349 if (!state.installed || state.hidden) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005350 return true;
5351 }
5352 if (state.stopped) {
5353 return true;
5354 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005355 if ((flags & PackageManager.GET_META_DATA) != 0
5356 && (metaData != null || p.mAppMetaData != null)) {
5357 return true;
5358 }
5359 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
5360 && p.usesLibraryFiles != null) {
5361 return true;
5362 }
5363 return false;
5364 }
5365
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005366 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
5367 PackageUserState state) {
5368 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07005369 }
5370
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08005371 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
5372 PackageUserState state) {
5373 // CompatibilityMode is global state.
5374 if (!sCompatibilityModeEnabled) {
5375 ai.disableCompatibilityMode();
5376 }
5377 if (state.installed) {
5378 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
5379 } else {
5380 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
5381 }
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00005382 if (state.suspended) {
5383 ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
5384 } else {
5385 ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
5386 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07005387 if (state.hidden) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005388 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07005389 } else {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005390 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07005391 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08005392 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
5393 ai.enabled = true;
5394 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
5395 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
5396 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
5397 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
5398 ai.enabled = false;
5399 }
5400 ai.enabledSetting = state.enabled;
5401 }
5402
Amith Yamasani13593602012-03-22 16:16:17 -07005403 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005404 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005405 if (p == null) return null;
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07005406 if (!checkUseInstalledOrHidden(flags, state) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005407 return null;
5408 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08005409 if (!copyNeeded(flags, p, state, null, userId)
5410 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
5411 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
5412 // In this case it is safe to directly modify the internal ApplicationInfo state:
5413 // - CompatibilityMode is global state, so will be the same for every call.
5414 // - We only come in to here if the app should reported as installed; this is the
5415 // default state, and we will do a copy otherwise.
5416 // - The enable state will always be reported the same for the application across
5417 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
5418 // be doing a copy.
5419 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005420 return p.applicationInfo;
5421 }
5422
5423 // Make shallow copy so we can store the metadata/libraries safely
5424 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Jeff Sharkey15447792015-11-05 16:18:51 -08005425 ai.initForUser(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005426 if ((flags & PackageManager.GET_META_DATA) != 0) {
5427 ai.metaData = p.mAppMetaData;
5428 }
5429 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
5430 ai.sharedLibraryFiles = p.usesLibraryFiles;
5431 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005432 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07005433 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08005434 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07005435 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08005436 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08005437 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005438 return ai;
5439 }
5440
Dianne Hackbornace27912014-09-18 18:38:30 -07005441 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
5442 PackageUserState state, int userId) {
5443 if (ai == null) return null;
5444 if (!checkUseInstalledOrHidden(flags, state)) {
5445 return null;
5446 }
5447 // This is only used to return the ResolverActivity; we will just always
5448 // make a copy.
5449 ai = new ApplicationInfo(ai);
Jeff Sharkey15447792015-11-05 16:18:51 -08005450 ai.initForUser(userId);
Dianne Hackbornace27912014-09-18 18:38:30 -07005451 if (state.stopped) {
5452 ai.flags |= ApplicationInfo.FLAG_STOPPED;
5453 } else {
5454 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
5455 }
5456 updateApplicationInfo(ai, flags, state);
5457 return ai;
5458 }
5459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005460 public static final PermissionInfo generatePermissionInfo(
5461 Permission p, int flags) {
5462 if (p == null) return null;
5463 if ((flags&PackageManager.GET_META_DATA) == 0) {
5464 return p.info;
5465 }
5466 PermissionInfo pi = new PermissionInfo(p.info);
5467 pi.metaData = p.metaData;
5468 return pi;
5469 }
5470
5471 public static final PermissionGroupInfo generatePermissionGroupInfo(
5472 PermissionGroup pg, int flags) {
5473 if (pg == null) return null;
5474 if ((flags&PackageManager.GET_META_DATA) == 0) {
5475 return pg.info;
5476 }
5477 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
5478 pgi.metaData = pg.metaData;
5479 return pgi;
5480 }
5481
5482 public final static class Activity extends Component<ActivityIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005483 public final ActivityInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005484
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005485 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
5486 super(args, _info);
5487 info = _info;
5488 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005489 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005490
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005491 public void setPackageName(String packageName) {
5492 super.setPackageName(packageName);
5493 info.packageName = packageName;
5494 }
5495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005496 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005497 StringBuilder sb = new StringBuilder(128);
5498 sb.append("Activity{");
5499 sb.append(Integer.toHexString(System.identityHashCode(this)));
5500 sb.append(' ');
5501 appendComponentShortName(sb);
5502 sb.append('}');
5503 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005504 }
5505 }
5506
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005507 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
5508 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005509 if (a == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07005510 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005511 return null;
5512 }
5513 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005514 return a.info;
5515 }
5516 // Make shallow copies so we can store the metadata safely
5517 ActivityInfo ai = new ActivityInfo(a.info);
5518 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005519 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005520 return ai;
5521 }
5522
Dianne Hackbornace27912014-09-18 18:38:30 -07005523 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
5524 PackageUserState state, int userId) {
5525 if (ai == null) return null;
5526 if (!checkUseInstalledOrHidden(flags, state)) {
5527 return null;
5528 }
5529 // This is only used to return the ResolverActivity; we will just always
5530 // make a copy.
5531 ai = new ActivityInfo(ai);
5532 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
5533 return ai;
5534 }
5535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005536 public final static class Service extends Component<ServiceIntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005537 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005538
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005539 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
5540 super(args, _info);
5541 info = _info;
5542 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005543 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005544
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005545 public void setPackageName(String packageName) {
5546 super.setPackageName(packageName);
5547 info.packageName = packageName;
5548 }
5549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005550 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005551 StringBuilder sb = new StringBuilder(128);
5552 sb.append("Service{");
5553 sb.append(Integer.toHexString(System.identityHashCode(this)));
5554 sb.append(' ');
5555 appendComponentShortName(sb);
5556 sb.append('}');
5557 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005558 }
5559 }
5560
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005561 public static final ServiceInfo generateServiceInfo(Service s, int flags,
5562 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005563 if (s == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07005564 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005565 return null;
5566 }
5567 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005568 return s.info;
5569 }
5570 // Make shallow copies so we can store the metadata safely
5571 ServiceInfo si = new ServiceInfo(s.info);
5572 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005573 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005574 return si;
5575 }
5576
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005577 public final static class Provider extends Component<ProviderIntentInfo> {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005578 public final ProviderInfo info;
5579 public boolean syncable;
5580
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005581 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
5582 super(args, _info);
5583 info = _info;
5584 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005585 syncable = false;
5586 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005588 public Provider(Provider existingProvider) {
5589 super(existingProvider);
5590 this.info = existingProvider.info;
5591 this.syncable = existingProvider.syncable;
5592 }
5593
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005594 public void setPackageName(String packageName) {
5595 super.setPackageName(packageName);
5596 info.packageName = packageName;
5597 }
5598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005599 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005600 StringBuilder sb = new StringBuilder(128);
5601 sb.append("Provider{");
5602 sb.append(Integer.toHexString(System.identityHashCode(this)));
5603 sb.append(' ');
5604 appendComponentShortName(sb);
5605 sb.append('}');
5606 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005607 }
5608 }
5609
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005610 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
5611 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005612 if (p == null) return null;
Amith Yamasanie5bcff62014-07-19 15:44:09 -07005613 if (!checkUseInstalledOrHidden(flags, state)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005614 return null;
5615 }
5616 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005617 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005618 || p.info.uriPermissionPatterns == null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005619 return p.info;
5620 }
5621 // Make shallow copies so we can store the metadata safely
5622 ProviderInfo pi = new ProviderInfo(p.info);
5623 pi.metaData = p.metaData;
5624 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
5625 pi.uriPermissionPatterns = null;
5626 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07005627 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005628 return pi;
5629 }
5630
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07005631 public final static class Instrumentation extends Component<IntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005632 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005633
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005634 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
5635 super(args, _info);
5636 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005637 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005638
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005639 public void setPackageName(String packageName) {
5640 super.setPackageName(packageName);
5641 info.packageName = packageName;
5642 }
5643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005644 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005645 StringBuilder sb = new StringBuilder(128);
5646 sb.append("Instrumentation{");
5647 sb.append(Integer.toHexString(System.identityHashCode(this)));
5648 sb.append(' ');
5649 appendComponentShortName(sb);
5650 sb.append('}');
5651 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005652 }
5653 }
5654
5655 public static final InstrumentationInfo generateInstrumentationInfo(
5656 Instrumentation i, int flags) {
5657 if (i == null) return null;
5658 if ((flags&PackageManager.GET_META_DATA) == 0) {
5659 return i.info;
5660 }
5661 InstrumentationInfo ii = new InstrumentationInfo(i.info);
5662 ii.metaData = i.metaData;
5663 return ii;
5664 }
5665
5666 public static class IntentInfo extends IntentFilter {
5667 public boolean hasDefault;
5668 public int labelRes;
5669 public CharSequence nonLocalizedLabel;
5670 public int icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07005671 public int logo;
Jose Limaf78e3122014-03-06 12:13:15 -08005672 public int banner;
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005673 public int preferred;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005674 }
5675
5676 public final static class ActivityIntentInfo extends IntentInfo {
5677 public final Activity activity;
5678
5679 public ActivityIntentInfo(Activity _activity) {
5680 activity = _activity;
5681 }
5682
5683 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005684 StringBuilder sb = new StringBuilder(128);
5685 sb.append("ActivityIntentInfo{");
5686 sb.append(Integer.toHexString(System.identityHashCode(this)));
5687 sb.append(' ');
5688 activity.appendComponentShortName(sb);
5689 sb.append('}');
5690 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005691 }
5692 }
5693
5694 public final static class ServiceIntentInfo extends IntentInfo {
5695 public final Service service;
5696
5697 public ServiceIntentInfo(Service _service) {
5698 service = _service;
5699 }
5700
5701 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07005702 StringBuilder sb = new StringBuilder(128);
5703 sb.append("ServiceIntentInfo{");
5704 sb.append(Integer.toHexString(System.identityHashCode(this)));
5705 sb.append(' ');
5706 service.appendComponentShortName(sb);
5707 sb.append('}');
5708 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005709 }
5710 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005711
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005712 public static final class ProviderIntentInfo extends IntentInfo {
5713 public final Provider provider;
5714
5715 public ProviderIntentInfo(Provider provider) {
5716 this.provider = provider;
5717 }
5718
5719 public String toString() {
5720 StringBuilder sb = new StringBuilder(128);
5721 sb.append("ProviderIntentInfo{");
5722 sb.append(Integer.toHexString(System.identityHashCode(this)));
5723 sb.append(' ');
5724 provider.appendComponentShortName(sb);
5725 sb.append('}');
5726 return sb.toString();
5727 }
5728 }
5729
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005730 /**
5731 * @hide
5732 */
5733 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
5734 sCompatibilityModeEnabled = compatibilityModeEnabled;
5735 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005736
Jeff Sharkey275e0852014-06-17 18:18:49 -07005737 private static AtomicReference<byte[]> sBuffer = new AtomicReference<byte[]>();
5738
5739 public static long readFullyIgnoringContents(InputStream in) throws IOException {
5740 byte[] buffer = sBuffer.getAndSet(null);
5741 if (buffer == null) {
5742 buffer = new byte[4096];
5743 }
5744
5745 int n = 0;
5746 int count = 0;
5747 while ((n = in.read(buffer, 0, buffer.length)) != -1) {
5748 count += n;
5749 }
5750
5751 sBuffer.set(buffer);
5752 return count;
5753 }
5754
5755 public static void closeQuietly(StrictJarFile jarFile) {
5756 if (jarFile != null) {
5757 try {
5758 jarFile.close();
5759 } catch (Exception ignored) {
5760 }
5761 }
5762 }
5763
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005764 public static class PackageParserException extends Exception {
5765 public final int error;
5766
5767 public PackageParserException(int error, String detailMessage) {
5768 super(detailMessage);
5769 this.error = error;
5770 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07005771
5772 public PackageParserException(int error, String detailMessage, Throwable throwable) {
5773 super(detailMessage, throwable);
5774 this.error = error;
5775 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005776 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005777}