blob: d4e43e58b5d500fb8dc69ec68589b4944fcfbbd3 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.content.pm;
18
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070019import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
Winson Chungd3395382016-12-13 11:49:09 -080020import static android.content.pm.ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070021import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
22import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
23import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
24import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
25import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070026import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
27import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
28import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
29import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
Wale Ogunwalee633eb02017-03-30 12:57:29 -070030import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
31import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Garrett Boyer52136662017-05-23 13:47:58 -070032import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070033import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
34import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
35import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
36import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
37import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
38import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
39import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
40import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -070041import static android.os.Build.VERSION_CODES.O;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070042import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
Robert Carr427ba4f2017-07-17 18:37:06 -070043import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070044
Alan Viverette82f4b263a2016-12-19 15:40:05 -050045import android.annotation.IntRange;
46import android.annotation.NonNull;
Fyodor Kupolov965fa692016-10-28 18:20:25 -070047import android.annotation.Nullable;
Alan Viverette82f4b263a2016-12-19 15:40:05 -050048import android.annotation.TestApi;
Dianne Hackborn852975d2014-08-22 17:42:43 -070049import android.app.ActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.content.ComponentName;
51import android.content.Intent;
52import android.content.IntentFilter;
Makoto Onuki4501c61d2017-07-27 15:56:40 -070053import android.content.pm.PackageParserCacheHelper.ReadHelper;
54import android.content.pm.PackageParserCacheHelper.WriteHelper;
Garrett Boyer52136662017-05-23 13:47:58 -070055import android.content.pm.split.DefaultSplitAssetLoader;
Adam Lesinski4e862812016-11-21 16:02:24 -080056import android.content.pm.split.SplitAssetDependencyLoader;
57import android.content.pm.split.SplitAssetLoader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.content.res.AssetManager;
59import android.content.res.Configuration;
60import android.content.res.Resources;
61import android.content.res.TypedArray;
62import android.content.res.XmlResourceParser;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -070063import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.os.Bundle;
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -070065import android.os.FileUtils;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070066import android.os.Parcel;
67import android.os.Parcelable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068import android.os.PatternMatcher;
Fyodor Kupolov28a988f2017-07-31 18:44:11 -070069import android.os.SystemClock;
Todd Leeea2f3be2017-03-16 14:00:52 -070070import android.os.SystemProperties;
Todd Kennedy27c24fb2015-09-17 16:49:25 -070071import android.os.Trace;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070072import android.os.UserHandle;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -060073import android.os.storage.StorageManager;
Narayan Kamath988149c2016-12-01 13:32:59 +000074import android.system.ErrnoException;
75import android.system.OsConstants;
76import android.system.StructStat;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -070077import android.text.TextUtils;
Jeff Sharkey275e0852014-06-17 18:18:49 -070078import android.util.ArrayMap;
79import android.util.ArraySet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.util.AttributeSet;
Kenny Root05ca4c92011-09-15 10:36:25 -070081import android.util.Base64;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.util.DisplayMetrics;
Kenny Root05ca4c92011-09-15 10:36:25 -070083import android.util.Log;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070084import android.util.Pair;
Kenny Rootd2d29252011-08-08 11:27:57 -070085import android.util.Slog;
Adam Lesinski1665d0f2017-03-10 14:46:57 -080086import android.util.SparseArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.util.TypedValue;
Alex Klyubine4157182016-01-05 13:27:05 -080088import android.util.apk.ApkSignatureSchemeV2Verifier;
Jeff Sharkeyc5967e92016-01-07 18:50:29 -070089import android.util.jar.StrictJarFile;
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -070090import android.view.Gravity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070092import com.android.internal.R;
93import com.android.internal.annotations.VisibleForTesting;
Narayan Kamathf9419f02017-06-15 11:35:38 +010094import com.android.internal.os.ClassLoaderFactory;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070095import com.android.internal.util.ArrayUtils;
96import com.android.internal.util.XmlUtils;
97
98import libcore.io.IoUtils;
99
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -0700100import libcore.util.EmptyArray;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -0700101import org.xmlpull.v1.XmlPullParser;
102import org.xmlpull.v1.XmlPullParserException;
103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import java.io.File;
Narayan Kamath988149c2016-12-01 13:32:59 +0000105import java.io.FileOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import java.io.IOException;
107import java.io.InputStream;
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -0700108import java.io.PrintWriter;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000109import java.lang.reflect.Constructor;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700110import java.security.GeneralSecurityException;
Kenny Root05ca4c92011-09-15 10:36:25 -0700111import java.security.KeyFactory;
112import java.security.NoSuchAlgorithmException;
113import java.security.PublicKey;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import java.security.cert.Certificate;
115import java.security.cert.CertificateEncodingException;
Kenny Root05ca4c92011-09-15 10:36:25 -0700116import java.security.spec.EncodedKeySpec;
117import java.security.spec.InvalidKeySpecException;
118import java.security.spec.X509EncodedKeySpec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119import java.util.ArrayList;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700120import java.util.Arrays;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700121import java.util.Collections;
122import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123import java.util.Iterator;
Kenny Root05ca4c92011-09-15 10:36:25 -0700124import java.util.List;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800125import java.util.Set;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -0600126import java.util.UUID;
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700127import java.util.concurrent.atomic.AtomicInteger;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700128import java.util.concurrent.atomic.AtomicReference;
Kenny Root6c918ce2013-04-02 14:04:24 -0700129import java.util.zip.ZipEntry;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130
131/**
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700132 * Parser for package files (APKs) on disk. This supports apps packaged either
133 * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
134 * APKs in a single directory.
135 * <p>
136 * Apps packaged as multiple APKs always consist of a single "base" APK (with a
137 * {@code null} split name) and zero or more "split" APKs (with unique split
138 * names). Any subset of those split APKs are a valid install, as long as the
139 * following constraints are met:
140 * <ul>
141 * <li>All APKs must have the exact same package name, version code, and signing
142 * certificates.
143 * <li>All APKs must have unique split names.
144 * <li>All installations must contain a single base APK.
145 * </ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700147 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 */
149public class PackageParser {
Kenny Rootd2d29252011-08-08 11:27:57 -0700150 private static final boolean DEBUG_JAR = false;
151 private static final boolean DEBUG_PARSER = false;
152 private static final boolean DEBUG_BACKUP = false;
Fyodor Kupolov28a988f2017-07-31 18:44:11 -0700153 private static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE;
154 private static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100;
Kenny Rootd2d29252011-08-08 11:27:57 -0700155
Svet Ganova3c4eb32017-04-19 23:51:33 -0700156 private static final String PROPERTY_CHILD_PACKAGES_ENABLED =
157 "persist.sys.child_packages_enabled";
158
Jeff Sharkey3f1790d2017-04-25 18:56:17 -0600159 private static final boolean MULTI_PACKAGE_APK_ENABLED = Build.IS_DEBUGGABLE &&
Garrett Boyer17041532017-08-01 14:11:02 -0700160 SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false);
Svet Ganova3c4eb32017-04-19 23:51:33 -0700161
Svet Ganov354cd3c2015-12-17 11:35:04 -0800162 private static final int MAX_PACKAGES_PER_APK = 5;
163
Todd Kennedy66c55532016-02-26 16:22:11 -0800164 public static final int APK_SIGNING_UNKNOWN = 0;
165 public static final int APK_SIGNING_V1 = 1;
166 public static final int APK_SIGNING_V2 = 2;
167
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700168 private static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f;
169
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700170 // TODO: switch outError users to PackageParserException
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700171 // TODO: refactor "codePath" to "apkPath"
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700172
Kenny Rootbcc954d2011-08-08 16:19:08 -0700173 /** File name in an APK for the Android manifest. */
174 private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
175
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700176 /** Path prefix for apps on expanded storage */
177 private static final String MNT_EXPAND = "/mnt/expand/";
178
Svet Ganov354cd3c2015-12-17 11:35:04 -0800179 private static final String TAG_MANIFEST = "manifest";
180 private static final String TAG_APPLICATION = "application";
Adam Lesinski4e862812016-11-21 16:02:24 -0800181 private static final String TAG_PACKAGE_VERIFIER = "package-verifier";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800182 private static final String TAG_OVERLAY = "overlay";
183 private static final String TAG_KEY_SETS = "key-sets";
184 private static final String TAG_PERMISSION_GROUP = "permission-group";
185 private static final String TAG_PERMISSION = "permission";
186 private static final String TAG_PERMISSION_TREE = "permission-tree";
187 private static final String TAG_USES_PERMISSION = "uses-permission";
188 private static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
189 private static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23";
190 private static final String TAG_USES_CONFIGURATION = "uses-configuration";
191 private static final String TAG_USES_FEATURE = "uses-feature";
192 private static final String TAG_FEATURE_GROUP = "feature-group";
193 private static final String TAG_USES_SDK = "uses-sdk";
194 private static final String TAG_SUPPORT_SCREENS = "supports-screens";
195 private static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
196 private static final String TAG_INSTRUMENTATION = "instrumentation";
197 private static final String TAG_ORIGINAL_PACKAGE = "original-package";
198 private static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
199 private static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
200 private static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
201 private static final String TAG_SUPPORTS_INPUT = "supports-input";
202 private static final String TAG_EAT_COMMENT = "eat-comment";
203 private static final String TAG_PACKAGE = "package";
Todd Kennedyfdd241a2016-04-28 12:26:53 -0700204 private static final String TAG_RESTRICT_UPDATE = "restrict-update";
Adam Lesinski4e862812016-11-21 16:02:24 -0800205 private static final String TAG_USES_SPLIT = "uses-split";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800206
Todd Kennedyfe7f38c32017-03-23 09:51:21 -0700207 // [b/36551762] STOPSHIP remove the ability to expose components via meta-data
Todd Kennedy752fb702017-03-21 16:28:10 -0700208 // Temporary workaround; allow meta-data to expose components to instant apps
209 private static final String META_DATA_INSTANT_APPS = "instantapps.clients.allowed";
210
Bryce Lee22571db2017-07-07 15:54:18 -0700211 private static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
212
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800213 /**
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700214 * Bit mask of all the valid bits that can be set in recreateOnConfigChanges.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800215 * @hide
216 */
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700217 private static final int RECREATE_ON_CONFIG_CHANGES_MASK =
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800218 ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC;
219
Svet Ganov354cd3c2015-12-17 11:35:04 -0800220 // These are the tags supported by child packages
221 private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>();
222 static {
223 CHILD_PACKAGE_TAGS.add(TAG_APPLICATION);
224 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION);
225 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_M);
226 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_23);
227 CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION);
228 CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE);
229 CHILD_PACKAGE_TAGS.add(TAG_FEATURE_GROUP);
230 CHILD_PACKAGE_TAGS.add(TAG_USES_SDK);
231 CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS);
232 CHILD_PACKAGE_TAGS.add(TAG_INSTRUMENTATION);
233 CHILD_PACKAGE_TAGS.add(TAG_USES_GL_TEXTURE);
234 CHILD_PACKAGE_TAGS.add(TAG_COMPATIBLE_SCREENS);
235 CHILD_PACKAGE_TAGS.add(TAG_SUPPORTS_INPUT);
236 CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
237 }
238
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700239 private static final boolean LOG_UNSAFE_BROADCASTS = false;
240
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700241 /**
242 * Total number of packages that were read from the cache. We use it only for logging.
243 */
244 public static final AtomicInteger sCachedPackageReadCount = new AtomicInteger();
245
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700246 // Set of broadcast actions that are safe for manifest receivers
247 private static final Set<String> SAFE_BROADCASTS = new ArraySet<>();
248 static {
249 SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED);
250 }
251
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700252 /** @hide */
253 public static class NewPermissionInfo {
254 public final String name;
255 public final int sdkVersion;
256 public final int fileVersion;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700257
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700258 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
259 this.name = name;
260 this.sdkVersion = sdkVersion;
261 this.fileVersion = fileVersion;
262 }
263 }
Dianne Hackborn79245122012-03-12 10:51:26 -0700264
265 /** @hide */
266 public static class SplitPermissionInfo {
267 public final String rootPerm;
268 public final String[] newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700269 public final int targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700270
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700271 public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
Dianne Hackborn79245122012-03-12 10:51:26 -0700272 this.rootPerm = rootPerm;
273 this.newPerms = newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700274 this.targetSdk = targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700275 }
276 }
277
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700278 /**
279 * List of new permissions that have been added since 1.0.
280 * NOTE: These must be declared in SDK version order, with permissions
281 * added to older SDKs appearing before those added to newer SDKs.
Dianne Hackborn79245122012-03-12 10:51:26 -0700282 * If sdkVersion is 0, then this is not a permission that we want to
283 * automatically add to older apps, but we do want to allow it to be
284 * granted during a platform update.
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700285 * @hide
286 */
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700287 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
288 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -0700289 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700290 android.os.Build.VERSION_CODES.DONUT, 0),
291 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
292 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700293 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294
Dianne Hackborn79245122012-03-12 10:51:26 -0700295 /**
296 * List of permissions that have been split into more granular or dependent
297 * permissions.
298 * @hide
299 */
300 public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
301 new PackageParser.SplitPermissionInfo[] {
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700302 // READ_EXTERNAL_STORAGE is always required when an app requests
303 // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
304 // write access without read access. The hack here with the target
305 // target SDK version ensures that this grant is always done.
Dianne Hackborn79245122012-03-12 10:51:26 -0700306 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700307 new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700308 android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700309 new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
310 new String[] { android.Manifest.permission.READ_CALL_LOG },
311 android.os.Build.VERSION_CODES.JELLY_BEAN),
312 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
313 new String[] { android.Manifest.permission.WRITE_CALL_LOG },
314 android.os.Build.VERSION_CODES.JELLY_BEAN)
Dianne Hackborn79245122012-03-12 10:51:26 -0700315 };
316
Jeff Sharkey275e0852014-06-17 18:18:49 -0700317 /**
318 * @deprecated callers should move to explicitly passing around source path.
319 */
320 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 private String mArchiveSourcePath;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700324 private boolean mOnlyCoreApps;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700325 private DisplayMetrics mMetrics;
Dianne Hackborncd154e92017-02-28 17:37:35 -0800326 private Callback mCallback;
Narayan Kamath988149c2016-12-01 13:32:59 +0000327 private File mCacheDir;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700328
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700329 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700330 private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800331
332 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
333
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700334 private static boolean sCompatibilityModeEnabled = true;
Amith Yamasani655d0e22013-06-12 14:19:10 -0700335 private static final int PARSE_DEFAULT_INSTALL_LOCATION =
336 PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Todd Kennedy11e45072017-01-25 13:24:21 -0800337 private static final int PARSE_DEFAULT_TARGET_SANDBOX = 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700338
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700339 static class ParsePackageItemArgs {
340 final Package owner;
341 final String[] outError;
342 final int nameRes;
343 final int labelRes;
344 final int iconRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700345 final int roundIconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700346 final int logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800347 final int bannerRes;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700348
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700349 String tag;
350 TypedArray sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700351
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700352 ParsePackageItemArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700353 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
354 int _bannerRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700355 owner = _owner;
356 outError = _outError;
357 nameRes = _nameRes;
358 labelRes = _labelRes;
359 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700360 logoRes = _logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800361 bannerRes = _bannerRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700362 roundIconRes = _roundIconRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700363 }
364 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700365
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000366 /** @hide */
367 @VisibleForTesting
368 public static class ParseComponentArgs extends ParsePackageItemArgs {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700369 final String[] sepProcesses;
370 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800371 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700372 final int enabledRes;
373 int flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700374
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000375 public ParseComponentArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700376 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
377 int _bannerRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800378 String[] _sepProcesses, int _processRes,
379 int _descriptionRes, int _enabledRes) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700380 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _roundIconRes, _logoRes,
381 _bannerRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700382 sepProcesses = _sepProcesses;
383 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800384 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700385 enabledRes = _enabledRes;
386 }
387 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800388
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700389 /**
Jeff Sharkey73767b92014-07-04 20:18:13 -0700390 * Lightweight parsed details about a single package.
391 */
392 public static class PackageLite {
393 public final String packageName;
394 public final int versionCode;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700395 public final int installLocation;
396 public final VerifierInfo[] verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700397
398 /** Names of any split APKs, ordered by parsed splitName */
399 public final String[] splitNames;
400
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800401 /** Names of any split APKs that are features. Ordered by splitName */
402 public final boolean[] isFeatureSplits;
403
Adam Lesinski4e862812016-11-21 16:02:24 -0800404 /** Dependencies of any split APKs, ordered by parsed splitName */
405 public final String[] usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800406 public final String[] configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800407
Jeff Sharkey73767b92014-07-04 20:18:13 -0700408 /**
409 * Path where this package was found on disk. For monolithic packages
410 * this is path to single base APK file; for cluster packages this is
411 * path to the cluster directory.
412 */
413 public final String codePath;
414
415 /** Path of base APK */
416 public final String baseCodePath;
417 /** Paths of any split APKs, ordered by parsed splitName */
418 public final String[] splitCodePaths;
419
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800420 /** Revision code of base APK */
421 public final int baseRevisionCode;
422 /** Revision codes of any split APKs, ordered by parsed splitName */
423 public final int[] splitRevisionCodes;
424
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700425 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100426 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100427 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800428 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700429 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800430 public final boolean isolatedSplits;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100431
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700432 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800433 boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100434 String[] splitCodePaths, int[] splitRevisionCodes) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700435 this.packageName = baseApk.packageName;
436 this.versionCode = baseApk.versionCode;
437 this.installLocation = baseApk.installLocation;
438 this.verifiers = baseApk.verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700439 this.splitNames = splitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800440 this.isFeatureSplits = isFeatureSplits;
Adam Lesinski4e862812016-11-21 16:02:24 -0800441 this.usesSplitNames = usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800442 this.configForSplit = configForSplit;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700443 this.codePath = codePath;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700444 this.baseCodePath = baseApk.codePath;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700445 this.splitCodePaths = splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800446 this.baseRevisionCode = baseApk.revisionCode;
447 this.splitRevisionCodes = splitRevisionCodes;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700448 this.coreApp = baseApk.coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100449 this.debuggable = baseApk.debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100450 this.multiArch = baseApk.multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800451 this.use32bitAbi = baseApk.use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700452 this.extractNativeLibs = baseApk.extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800453 this.isolatedSplits = baseApk.isolatedSplits;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700454 }
455
456 public List<String> getAllCodePaths() {
457 ArrayList<String> paths = new ArrayList<>();
458 paths.add(baseCodePath);
459 if (!ArrayUtils.isEmpty(splitCodePaths)) {
460 Collections.addAll(paths, splitCodePaths);
461 }
462 return paths;
463 }
464 }
465
466 /**
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700467 * Lightweight parsed details about a single APK file.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800468 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700469 public static class ApkLite {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700470 public final String codePath;
Kenny Root05ca4c92011-09-15 10:36:25 -0700471 public final String packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700472 public final String splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800473 public boolean isFeatureSplit;
474 public final String configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800475 public final String usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700476 public final int versionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800477 public final int revisionCode;
Kenny Root05ca4c92011-09-15 10:36:25 -0700478 public final int installLocation;
479 public final VerifierInfo[] verifiers;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700480 public final Signature[] signatures;
Todd Kennedyd9d438a2016-04-06 14:08:14 -0700481 public final Certificate[][] certificates;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700482 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100483 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100484 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800485 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700486 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800487 public final boolean isolatedSplits;
Kenny Root05ca4c92011-09-15 10:36:25 -0700488
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800489 public ApkLite(String codePath, String packageName, String splitName, boolean isFeatureSplit,
490 String configForSplit, String usesSplitName, int versionCode, int revisionCode,
491 int installLocation, List<VerifierInfo> verifiers, Signature[] signatures,
492 Certificate[][] certificates, boolean coreApp, boolean debuggable,
493 boolean multiArch, boolean use32bitAbi, boolean extractNativeLibs,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100494 boolean isolatedSplits) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700495 this.codePath = codePath;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800496 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700497 this.splitName = splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800498 this.isFeatureSplit = isFeatureSplit;
499 this.configForSplit = configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800500 this.usesSplitName = usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700501 this.versionCode = versionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800502 this.revisionCode = revisionCode;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800503 this.installLocation = installLocation;
Kenny Root05ca4c92011-09-15 10:36:25 -0700504 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700505 this.signatures = signatures;
Todd Kennedyd9d438a2016-04-06 14:08:14 -0700506 this.certificates = certificates;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700507 this.coreApp = coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100508 this.debuggable = debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100509 this.multiArch = multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800510 this.use32bitAbi = use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700511 this.extractNativeLibs = extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800512 this.isolatedSplits = isolatedSplits;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800513 }
514 }
515
Garrett Boyer52136662017-05-23 13:47:58 -0700516 /**
517 * Cached parse state for new components.
518 *
519 * Allows reuse of the same parse argument records to avoid GC pressure. Lifetime is carefully
520 * scoped to the parsing of a single application element.
521 */
522 private static class CachedComponentArgs {
523 ParseComponentArgs mActivityArgs;
524 ParseComponentArgs mActivityAliasArgs;
525 ParseComponentArgs mServiceArgs;
526 ParseComponentArgs mProviderArgs;
527 }
528
529 /**
530 * Cached state for parsing instrumentation to avoid GC pressure.
531 *
532 * Must be manually reset to null for each new manifest.
533 */
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700534 private ParsePackageItemArgs mParseInstrumentationArgs;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 /** If set to true, we will only allow package files that exactly match
537 * the DTD. Otherwise, we try to get as much from the package as we
538 * can without failing. This should normally be set to false, to
539 * support extensions to the DTD in future versions. */
540 private static final boolean RIGID_PARSER = false;
541
542 private static final String TAG = "PackageParser";
543
Jeff Sharkey275e0852014-06-17 18:18:49 -0700544 public PackageParser() {
545 mMetrics = new DisplayMetrics();
546 mMetrics.setToDefaults();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700547 }
548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 public void setSeparateProcesses(String[] procs) {
550 mSeparateProcesses = procs;
551 }
552
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700553 /**
554 * Flag indicating this parser should only consider apps with
555 * {@code coreApp} manifest attribute to be valid apps. This is useful when
556 * creating a minimalist boot environment.
557 */
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700558 public void setOnlyCoreApps(boolean onlyCoreApps) {
559 mOnlyCoreApps = onlyCoreApps;
560 }
561
Jeff Sharkey275e0852014-06-17 18:18:49 -0700562 public void setDisplayMetrics(DisplayMetrics metrics) {
563 mMetrics = metrics;
564 }
565
Narayan Kamath988149c2016-12-01 13:32:59 +0000566 /**
567 * Sets the cache directory for this package parser.
568 */
569 public void setCacheDir(File cacheDir) {
570 mCacheDir = cacheDir;
571 }
572
Dianne Hackborncd154e92017-02-28 17:37:35 -0800573 /**
574 * Callback interface for retrieving information that may be needed while parsing
575 * a package.
576 */
577 public interface Callback {
578 boolean hasFeature(String feature);
Jaekyun Seok30dc2a02017-04-11 09:41:11 +0900579 String[] getOverlayPaths(String targetPackageName, String targetPath);
580 String[] getOverlayApks(String targetPackageName);
Dianne Hackborncd154e92017-02-28 17:37:35 -0800581 }
582
583 /**
584 * Standard implementation of {@link Callback} on top of the public {@link PackageManager}
585 * class.
586 */
587 public static final class CallbackImpl implements Callback {
588 private final PackageManager mPm;
589
590 public CallbackImpl(PackageManager pm) {
591 mPm = pm;
592 }
593
594 @Override public boolean hasFeature(String feature) {
595 return mPm.hasSystemFeature(feature);
596 }
Jaekyun Seok30dc2a02017-04-11 09:41:11 +0900597
598 @Override public String[] getOverlayPaths(String targetPackageName, String targetPath) {
599 return null;
600 }
601
602 @Override public String[] getOverlayApks(String targetPackageName) {
603 return null;
604 }
Dianne Hackborncd154e92017-02-28 17:37:35 -0800605 }
606
607 /**
608 * Set the {@link Callback} that can be used while parsing.
609 */
610 public void setCallback(Callback cb) {
611 mCallback = cb;
612 }
613
Jeff Sharkey73767b92014-07-04 20:18:13 -0700614 public static final boolean isApkFile(File file) {
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700615 return isApkPath(file.getName());
616 }
617
Adam Lesinski4e862812016-11-21 16:02:24 -0800618 public static boolean isApkPath(String path) {
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700619 return path.endsWith(".apk");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800620 }
621
622 /**
623 * Generate and return the {@link PackageInfo} for a parsed package.
624 *
625 * @param p the parsed package.
626 * @param flags indicating which optional information is included.
627 */
628 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Dianne Hackborne639da72012-02-21 15:11:13 -0800629 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svet Ganov3695b8a2015-03-24 16:30:25 -0700630 Set<String> grantedPermissions, PackageUserState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631
Amith Yamasani483f3b02012-03-13 16:08:00 -0700632 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700633 grantedPermissions, state, UserHandle.getCallingUserId());
634 }
635
Amith Yamasani655d0e22013-06-12 14:19:10 -0700636 /**
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700637 * Returns true if the package is installed and not hidden, or if the caller
638 * explicitly wanted all uninstalled and hidden packages as well.
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700639 * @param appInfo The applicationInfo of the app being checked.
Amith Yamasani655d0e22013-06-12 14:19:10 -0700640 */
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700641 private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state,
642 ApplicationInfo appInfo) {
643 // If available for the target user, or trying to match uninstalled packages and it's
644 // a system app.
645 return state.isAvailable(flags)
646 || (appInfo != null && appInfo.isSystemApp()
647 && (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0);
Amith Yamasani483f3b02012-03-13 16:08:00 -0700648 }
649
Christopher Tateba629da2013-11-13 17:42:28 -0800650 public static boolean isAvailable(PackageUserState state) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700651 return checkUseInstalledOrHidden(0, state, null);
Christopher Tateba629da2013-11-13 17:42:28 -0800652 }
653
Amith Yamasani13593602012-03-22 16:16:17 -0700654 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Amith Yamasani483f3b02012-03-13 16:08:00 -0700655 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svetoslavc6d1c342015-02-26 14:44:43 -0800656 Set<String> grantedPermissions, PackageUserState state, int userId) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700657 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700658 return null;
659 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800660 PackageInfo pi = new PackageInfo();
661 pi.packageName = p.packageName;
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700662 pi.splitNames = p.splitNames;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663 pi.versionCode = p.mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800664 pi.baseRevisionCode = p.baseRevisionCode;
665 pi.splitRevisionCodes = p.splitRevisionCodes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800666 pi.versionName = p.mVersionName;
667 pi.sharedUserId = p.mSharedUserId;
668 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700669 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800670 pi.installLocation = p.installLocation;
Todd Kennedy7c8addf2017-06-27 14:13:55 -0700671 pi.isStub = p.isStub;
Jeff Hao272bf3a2014-10-08 13:34:43 -0700672 pi.coreApp = p.coreApp;
Amith Yamasani0d8750d2013-05-01 15:25:28 -0700673 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
674 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
675 pi.requiredForAllUsers = p.mRequiredForAllUsers;
676 }
Amith Yamasani0ac1fc92013-03-27 18:56:08 -0700677 pi.restrictedAccountType = p.mRestrictedAccountType;
Amith Yamasaniccbe3892013-04-12 17:52:42 -0700678 pi.requiredAccountType = p.mRequiredAccountType;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100679 pi.overlayTarget = p.mOverlayTarget;
Jaekyun Seok42d53f62017-04-10 13:48:58 +0900680 pi.overlayPriority = p.mOverlayPriority;
Jaekyun Seok04342892017-03-02 15:24:19 +0900681 pi.isStaticOverlay = p.mIsStaticOverlay;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700682 pi.firstInstallTime = firstInstallTime;
683 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 if ((flags&PackageManager.GET_GIDS) != 0) {
685 pi.gids = gids;
686 }
687 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700688 int N = p.configPreferences != null ? p.configPreferences.size() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689 if (N > 0) {
690 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700691 p.configPreferences.toArray(pi.configPreferences);
692 }
693 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
694 if (N > 0) {
695 pi.reqFeatures = new FeatureInfo[N];
696 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 }
Adam Lesinskid3edfde2014-08-08 17:32:44 -0700698 N = p.featureGroups != null ? p.featureGroups.size() : 0;
699 if (N > 0) {
700 pi.featureGroups = new FeatureGroupInfo[N];
701 p.featureGroups.toArray(pi.featureGroups);
702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700704 if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
705 final int N = p.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700707 int num = 0;
708 final ActivityInfo[] res = new ActivityInfo[N];
709 for (int i = 0; i < N; i++) {
710 final Activity a = p.activities.get(i);
711 if (state.isMatch(a.info, flags)) {
712 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713 }
714 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700715 pi.activities = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 }
717 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700718 if ((flags & PackageManager.GET_RECEIVERS) != 0) {
719 final int N = p.receivers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700721 int num = 0;
722 final ActivityInfo[] res = new ActivityInfo[N];
723 for (int i = 0; i < N; i++) {
724 final Activity a = p.receivers.get(i);
725 if (state.isMatch(a.info, flags)) {
726 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 }
728 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700729 pi.receivers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800730 }
731 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700732 if ((flags & PackageManager.GET_SERVICES) != 0) {
733 final int N = p.services.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700735 int num = 0;
736 final ServiceInfo[] res = new ServiceInfo[N];
737 for (int i = 0; i < N; i++) {
738 final Service s = p.services.get(i);
739 if (state.isMatch(s.info, flags)) {
740 res[num++] = generateServiceInfo(s, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800741 }
742 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700743 pi.services = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 }
745 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700746 if ((flags & PackageManager.GET_PROVIDERS) != 0) {
747 final int N = p.providers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700749 int num = 0;
750 final ProviderInfo[] res = new ProviderInfo[N];
751 for (int i = 0; i < N; i++) {
752 final Provider pr = p.providers.get(i);
753 if (state.isMatch(pr.info, flags)) {
754 res[num++] = generateProviderInfo(pr, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 }
756 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700757 pi.providers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800758 }
759 }
760 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
761 int N = p.instrumentation.size();
762 if (N > 0) {
763 pi.instrumentation = new InstrumentationInfo[N];
764 for (int i=0; i<N; i++) {
765 pi.instrumentation[i] = generateInstrumentationInfo(
766 p.instrumentation.get(i), flags);
767 }
768 }
769 }
770 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
771 int N = p.permissions.size();
772 if (N > 0) {
773 pi.permissions = new PermissionInfo[N];
774 for (int i=0; i<N; i++) {
775 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
776 }
777 }
778 N = p.requestedPermissions.size();
779 if (N > 0) {
780 pi.requestedPermissions = new String[N];
Dianne Hackborne639da72012-02-21 15:11:13 -0800781 pi.requestedPermissionsFlags = new int[N];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 for (int i=0; i<N; i++) {
Dianne Hackborne639da72012-02-21 15:11:13 -0800783 final String perm = p.requestedPermissions.get(i);
784 pi.requestedPermissions[i] = perm;
Svet Ganov3695b8a2015-03-24 16:30:25 -0700785 // The notion of required permissions is deprecated but for compatibility.
Svetoslavc6d1c342015-02-26 14:44:43 -0800786 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800787 if (grantedPermissions != null && grantedPermissions.contains(perm)) {
788 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790 }
791 }
792 }
793 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -0700794 int N = (p.mSignatures != null) ? p.mSignatures.length : 0;
795 if (N > 0) {
796 pi.signatures = new Signature[N];
797 System.arraycopy(p.mSignatures, 0, pi.signatures, 0, N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 }
799 }
800 return pi;
801 }
802
Jeff Sharkey275e0852014-06-17 18:18:49 -0700803 private static Certificate[][] loadCertificates(StrictJarFile jarFile, ZipEntry entry)
804 throws PackageParserException {
805 InputStream is = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800806 try {
807 // We must read the stream for the JarEntry to retrieve
808 // its certificates.
Jeff Sharkey275e0852014-06-17 18:18:49 -0700809 is = jarFile.getInputStream(entry);
810 readFullyIgnoringContents(is);
811 return jarFile.getCertificateChains(entry);
812 } catch (IOException | RuntimeException e) {
813 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
814 "Failed reading " + entry.getName() + " in " + jarFile, e);
815 } finally {
816 IoUtils.closeQuietly(is);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800818 }
819
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800820 public final static int PARSE_IS_SYSTEM = 1<<0;
821 public final static int PARSE_CHATTY = 1<<1;
822 public final static int PARSE_MUST_BE_APK = 1<<2;
823 public final static int PARSE_IGNORE_PROCESSES = 1<<3;
824 public final static int PARSE_FORWARD_LOCK = 1<<4;
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -0700825 public final static int PARSE_EXTERNAL_STORAGE = 1<<5;
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700826 public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
Christopher Tateccbf84f2013-05-08 15:25:41 -0700827 public final static int PARSE_IS_PRIVILEGED = 1<<7;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -0700828 public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700829 public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
Christopher Tatef3d939c2015-09-17 12:25:51 -0700830 public final static int PARSE_ENFORCE_CODE = 1<<10;
Todd Kennedybe0b8892017-02-15 14:13:52 -0800831 /** @deprecated remove when fixing b/34761192 */
832 @Deprecated
Todd Kennedy373f0b42015-12-16 14:45:14 -0800833 public final static int PARSE_IS_EPHEMERAL = 1<<11;
Todd Kennedyb1072712016-04-26 15:41:20 -0700834 public final static int PARSE_FORCE_SDK = 1<<12;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700835
836 private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800837
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700838 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700839 * Used to sort a set of APKs based on their split names, always placing the
840 * base APK (with {@code null} split name) first.
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700841 */
Jeff Sharkey275e0852014-06-17 18:18:49 -0700842 private static class SplitNameComparator implements Comparator<String> {
843 @Override
844 public int compare(String lhs, String rhs) {
845 if (lhs == null) {
846 return -1;
847 } else if (rhs == null) {
848 return 1;
849 } else {
850 return lhs.compareTo(rhs);
851 }
852 }
853 }
854
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700855 /**
856 * Parse only lightweight details about the package at the given location.
857 * Automatically detects if the package is a monolithic style (single APK
858 * file) or cluster style (directory of APKs).
859 * <p>
860 * This performs sanity checking on cluster style packages, such as
861 * requiring identical package name and version codes, a single base APK,
862 * and unique split names.
863 *
864 * @see PackageParser#parsePackage(File, int)
865 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700866 public static PackageLite parsePackageLite(File packageFile, int flags)
867 throws PackageParserException {
868 if (packageFile.isDirectory()) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800869 return parseClusterPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700870 } else {
Adam Lesinski4e862812016-11-21 16:02:24 -0800871 return parseMonolithicPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700872 }
873 }
874
Adam Lesinski4e862812016-11-21 16:02:24 -0800875 private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
876 throws PackageParserException {
Todd Kennedycd029da2016-07-21 07:41:09 -0700877 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Adam Lesinski4e862812016-11-21 16:02:24 -0800878 final ApkLite baseApk = parseApkLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700879 final String packagePath = packageFile.getAbsolutePath();
Todd Kennedycd029da2016-07-21 07:41:09 -0700880 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Narayan Kamath96c11c52017-08-09 13:07:21 +0100881 return new PackageLite(packagePath, baseApk, null, null, null, null, null, null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700882 }
883
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800884 static PackageLite parseClusterPackageLite(File packageDir, int flags)
Adam Lesinski4e862812016-11-21 16:02:24 -0800885 throws PackageParserException {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700886 final File[] files = packageDir.listFiles();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700887 if (ArrayUtils.isEmpty(files)) {
888 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
889 "No packages found in split");
890 }
891
Jeff Sharkey275e0852014-06-17 18:18:49 -0700892 String packageName = null;
893 int versionCode = 0;
894
Todd Kennedycd029da2016-07-21 07:41:09 -0700895 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700896 final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700897 for (File file : files) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700898 if (isApkFile(file)) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800899 final ApkLite lite = parseApkLite(file, flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -0700900
901 // Assert that all package names and version codes are
902 // consistent with the first one we encounter.
903 if (packageName == null) {
904 packageName = lite.packageName;
905 versionCode = lite.versionCode;
906 } else {
907 if (!packageName.equals(lite.packageName)) {
908 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
909 "Inconsistent package " + lite.packageName + " in " + file
910 + "; expected " + packageName);
911 }
912 if (versionCode != lite.versionCode) {
913 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
914 "Inconsistent version " + lite.versionCode + " in " + file
915 + "; expected " + versionCode);
916 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700917 }
918
Jeff Sharkey275e0852014-06-17 18:18:49 -0700919 // Assert that each split is defined only once
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700920 if (apks.put(lite.splitName, lite) != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700921 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
922 "Split name " + lite.splitName
923 + " defined more than once; most recent was " + file);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700924 }
925 }
926 }
Todd Kennedycd029da2016-07-21 07:41:09 -0700927 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700928
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700929 final ApkLite baseApk = apks.remove(null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700930 if (baseApk == null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700931 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
Jeff Sharkey73767b92014-07-04 20:18:13 -0700932 "Missing base APK in " + packageDir);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700933 }
934
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700935 // Always apply deterministic ordering based on splitName
936 final int size = apks.size();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700937
Jeff Sharkey73767b92014-07-04 20:18:13 -0700938 String[] splitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800939 boolean[] isFeatureSplits = null;
Adam Lesinski4e862812016-11-21 16:02:24 -0800940 String[] usesSplitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800941 String[] configForSplits = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700942 String[] splitCodePaths = null;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800943 int[] splitRevisionCodes = null;
Narayan Kamathf9419f02017-06-15 11:35:38 +0100944 String[] splitClassLoaderNames = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700945 if (size > 0) {
946 splitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800947 isFeatureSplits = new boolean[size];
Adam Lesinski4e862812016-11-21 16:02:24 -0800948 usesSplitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800949 configForSplits = new String[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700950 splitCodePaths = new String[size];
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800951 splitRevisionCodes = new int[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700952
953 splitNames = apks.keySet().toArray(splitNames);
954 Arrays.sort(splitNames, sSplitNameComparator);
955
956 for (int i = 0; i < size; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800957 final ApkLite apk = apks.get(splitNames[i]);
958 usesSplitNames[i] = apk.usesSplitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800959 isFeatureSplits[i] = apk.isFeatureSplit;
960 configForSplits[i] = apk.configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800961 splitCodePaths[i] = apk.codePath;
962 splitRevisionCodes[i] = apk.revisionCode;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700963 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700964 }
965
Jeff Sharkey73767b92014-07-04 20:18:13 -0700966 final String codePath = packageDir.getAbsolutePath();
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800967 return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100968 configForSplits, splitCodePaths, splitRevisionCodes);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700969 }
970
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700971 /**
972 * Parse the package at the given location. Automatically detects if the
973 * package is a monolithic style (single APK file) or cluster style
974 * (directory of APKs).
975 * <p>
976 * This performs sanity checking on cluster style packages, such as
977 * requiring identical package name and version codes, a single base APK,
978 * and unique split names.
979 * <p>
980 * Note that this <em>does not</em> perform signature verification; that
981 * must be done separately in {@link #collectCertificates(Package, int)}.
982 *
Narayan Kamath988149c2016-12-01 13:32:59 +0000983 * If {@code useCaches} is true, the package parser might return a cached
984 * result from a previous parse of the same {@code packageFile} with the same
985 * {@code flags}. Note that this method does not check whether {@code packageFile}
986 * has changed since the last parse, it's up to callers to do so.
987 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700988 * @see #parsePackageLite(File, int)
989 */
Narayan Kamath988149c2016-12-01 13:32:59 +0000990 public Package parsePackage(File packageFile, int flags, boolean useCaches)
991 throws PackageParserException {
992 Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
993 if (parsed != null) {
994 return parsed;
995 }
996
Fyodor Kupolov28a988f2017-07-31 18:44:11 -0700997 long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700998 if (packageFile.isDirectory()) {
Narayan Kamath988149c2016-12-01 13:32:59 +0000999 parsed = parseClusterPackage(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001000 } else {
Narayan Kamath988149c2016-12-01 13:32:59 +00001001 parsed = parseMonolithicPackage(packageFile, flags);
1002 }
1003
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001004 long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Narayan Kamath988149c2016-12-01 13:32:59 +00001005 cacheResult(packageFile, flags, parsed);
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001006 if (LOG_PARSE_TIMINGS) {
1007 parseTime = cacheTime - parseTime;
1008 cacheTime = SystemClock.uptimeMillis() - cacheTime;
1009 if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) {
1010 Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime
1011 + "ms, update_cache=" + cacheTime + " ms");
1012 }
1013 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001014 return parsed;
1015 }
1016
1017 /**
1018 * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}.
1019 */
1020 public Package parsePackage(File packageFile, int flags) throws PackageParserException {
1021 return parsePackage(packageFile, flags, false /* useCaches */);
1022 }
1023
1024 /**
1025 * Returns the cache key for a specificied {@code packageFile} and {@code flags}.
1026 */
1027 private String getCacheKey(File packageFile, int flags) {
1028 StringBuilder sb = new StringBuilder(packageFile.getName());
1029 sb.append('-');
1030 sb.append(flags);
1031
1032 return sb.toString();
1033 }
1034
1035 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001036 protected Package fromCacheEntry(byte[] bytes) {
1037 return fromCacheEntryStatic(bytes);
1038 }
1039
1040 /** static version of {@link #fromCacheEntry} for unit tests. */
1041 @VisibleForTesting
1042 public static Package fromCacheEntryStatic(byte[] bytes) {
1043 final Parcel p = Parcel.obtain();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001044 p.unmarshall(bytes, 0, bytes.length);
1045 p.setDataPosition(0);
1046
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001047 final ReadHelper helper = new ReadHelper(p);
1048 helper.startAndInstall();
1049
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001050 PackageParser.Package pkg = new PackageParser.Package(p);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001051
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001052 p.recycle();
1053
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001054 sCachedPackageReadCount.incrementAndGet();
1055
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001056 return pkg;
Narayan Kamath988149c2016-12-01 13:32:59 +00001057 }
1058
1059 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001060 protected byte[] toCacheEntry(Package pkg) {
1061 return toCacheEntryStatic(pkg);
1062
1063 }
1064
1065 /** static version of {@link #toCacheEntry} for unit tests. */
1066 @VisibleForTesting
1067 public static byte[] toCacheEntryStatic(Package pkg) {
1068 final Parcel p = Parcel.obtain();
1069 final WriteHelper helper = new WriteHelper(p);
1070
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001071 pkg.writeToParcel(p, 0 /* flags */);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001072
1073 helper.finishAndUninstall();
1074
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001075 byte[] serialized = p.marshall();
1076 p.recycle();
1077
1078 return serialized;
Narayan Kamath988149c2016-12-01 13:32:59 +00001079 }
1080
1081 /**
1082 * Given a {@code packageFile} and a {@code cacheFile} returns whether the
1083 * cache file is up to date based on the mod-time of both files.
1084 */
1085 private static boolean isCacheUpToDate(File packageFile, File cacheFile) {
1086 try {
1087 // NOTE: We don't use the File.lastModified API because it has the very
1088 // non-ideal failure mode of returning 0 with no excepions thrown.
1089 // The nio2 Files API is a little better but is considerably more expensive.
1090 final StructStat pkg = android.system.Os.stat(packageFile.getAbsolutePath());
1091 final StructStat cache = android.system.Os.stat(cacheFile.getAbsolutePath());
1092 return pkg.st_mtime < cache.st_mtime;
1093 } catch (ErrnoException ee) {
1094 // The most common reason why stat fails is that a given cache file doesn't
1095 // exist. We ignore that here. It's easy to reason that it's safe to say the
1096 // cache isn't up to date if we see any sort of exception here.
1097 //
1098 // (1) Exception while stating the package file : This should never happen,
1099 // and if it does, we do a full package parse (which is likely to throw the
1100 // same exception).
1101 // (2) Exception while stating the cache file : If the file doesn't exist, the
1102 // cache is obviously out of date. If the file *does* exist, we can't read it.
1103 // We will attempt to delete and recreate it after parsing the package.
1104 if (ee.errno != OsConstants.ENOENT) {
1105 Slog.w("Error while stating package cache : ", ee);
1106 }
1107
1108 return false;
1109 }
1110 }
1111
1112 /**
1113 * Returns the cached parse result for {@code packageFile} for parse flags {@code flags},
1114 * or {@code null} if no cached result exists.
1115 */
1116 private Package getCachedResult(File packageFile, int flags) {
1117 if (mCacheDir == null) {
1118 return null;
1119 }
1120
1121 final String cacheKey = getCacheKey(packageFile, flags);
1122 final File cacheFile = new File(mCacheDir, cacheKey);
1123
Narayan Kamath988149c2016-12-01 13:32:59 +00001124 try {
Makoto Onuki48e93162017-08-18 11:00:19 -07001125 // If the cache is not up to date, return null.
1126 if (!isCacheUpToDate(packageFile, cacheFile)) {
1127 return null;
1128 }
1129
Narayan Kamath988149c2016-12-01 13:32:59 +00001130 final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001131 Package p = fromCacheEntry(bytes);
1132 if (mCallback != null) {
1133 String[] overlayApks = mCallback.getOverlayApks(p.packageName);
1134 if (overlayApks != null && overlayApks.length > 0) {
1135 for (String overlayApk : overlayApks) {
1136 // If a static RRO is updated, return null.
1137 if (!isCacheUpToDate(new File(overlayApk), cacheFile)) {
1138 return null;
1139 }
1140 }
1141 }
1142 }
1143 return p;
Makoto Onuki48e93162017-08-18 11:00:19 -07001144 } catch (Throwable e) {
Narayan Kamath21a28382017-01-13 10:34:29 +00001145 Slog.w(TAG, "Error reading package cache: ", e);
Narayan Kamath988149c2016-12-01 13:32:59 +00001146
1147 // If something went wrong while reading the cache entry, delete the cache file
1148 // so that we regenerate it the next time.
1149 cacheFile.delete();
1150 return null;
1151 }
1152 }
1153
1154 /**
1155 * Caches the parse result for {@code packageFile} with flags {@code flags}.
1156 */
1157 private void cacheResult(File packageFile, int flags, Package parsed) {
1158 if (mCacheDir == null) {
1159 return;
1160 }
1161
Makoto Onuki48e93162017-08-18 11:00:19 -07001162 try {
1163 final String cacheKey = getCacheKey(packageFile, flags);
1164 final File cacheFile = new File(mCacheDir, cacheKey);
Narayan Kamath988149c2016-12-01 13:32:59 +00001165
Makoto Onuki48e93162017-08-18 11:00:19 -07001166 if (cacheFile.exists()) {
1167 if (!cacheFile.delete()) {
1168 Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
1169 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001170 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001171
Makoto Onuki48e93162017-08-18 11:00:19 -07001172 final byte[] cacheEntry = toCacheEntry(parsed);
Narayan Kamath988149c2016-12-01 13:32:59 +00001173
Makoto Onuki48e93162017-08-18 11:00:19 -07001174 if (cacheEntry == null) {
1175 return;
1176 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001177
Makoto Onuki48e93162017-08-18 11:00:19 -07001178 try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
1179 fos.write(cacheEntry);
1180 } catch (IOException ioe) {
1181 Slog.w(TAG, "Error writing cache entry.", ioe);
1182 cacheFile.delete();
1183 }
1184 } catch (Throwable e) {
1185 Slog.w(TAG, "Error saving package cache.", e);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001186 }
1187 }
1188
1189 /**
1190 * Parse all APKs contained in the given directory, treating them as a
1191 * single package. This also performs sanity checking, such as requiring
1192 * identical package name and version codes, a single base APK, and unique
1193 * split names.
1194 * <p>
1195 * Note that this <em>does not</em> perform signature verification; that
1196 * must be done separately in {@link #collectCertificates(Package, int)}.
1197 */
1198 private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
Adam Lesinski4e862812016-11-21 16:02:24 -08001199 final PackageLite lite = parseClusterPackageLite(packageDir, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001200 if (mOnlyCoreApps && !lite.coreApp) {
1201 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1202 "Not a coreApp: " + packageDir);
1203 }
1204
Adam Lesinski4e862812016-11-21 16:02:24 -08001205 // Build the split dependency tree.
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001206 SparseArray<int[]> splitDependencies = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001207 final SplitAssetLoader assetLoader;
1208 if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) {
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001209 try {
1210 splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite);
1211 assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags);
1212 } catch (SplitAssetDependencyLoader.IllegalDependencyException e) {
1213 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage());
1214 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001215 } else {
1216 assetLoader = new DefaultSplitAssetLoader(lite, flags);
1217 }
1218
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001219 try {
Adam Lesinski4e862812016-11-21 16:02:24 -08001220 final AssetManager assets = assetLoader.getBaseAssetManager();
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001221 final File baseApk = new File(lite.baseCodePath);
1222 final Package pkg = parseBaseApk(baseApk, assets, flags);
1223 if (pkg == null) {
1224 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1225 "Failed to parse base APK: " + baseApk);
1226 }
1227
1228 if (!ArrayUtils.isEmpty(lite.splitNames)) {
1229 final int num = lite.splitNames.length;
1230 pkg.splitNames = lite.splitNames;
1231 pkg.splitCodePaths = lite.splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001232 pkg.splitRevisionCodes = lite.splitRevisionCodes;
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001233 pkg.splitFlags = new int[num];
Alex Klyubinb9f8a522015-02-03 11:12:59 -08001234 pkg.splitPrivateFlags = new int[num];
Adam Lesinski4e862812016-11-21 16:02:24 -08001235 pkg.applicationInfo.splitNames = pkg.splitNames;
1236 pkg.applicationInfo.splitDependencies = splitDependencies;
Narayan Kamath96c11c52017-08-09 13:07:21 +01001237 pkg.applicationInfo.splitClassLoaderNames = new String[num];
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001238
1239 for (int i = 0; i < num; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -08001240 final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
1241 parseSplitApk(pkg, i, splitAssets, flags);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001242 }
1243 }
1244
Svet Ganov354cd3c2015-12-17 11:35:04 -08001245 pkg.setCodePath(packageDir.getAbsolutePath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001246 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001247 return pkg;
1248 } finally {
Adam Lesinski4e862812016-11-21 16:02:24 -08001249 IoUtils.closeQuietly(assetLoader);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001251 }
1252
Jeff Sharkey275e0852014-06-17 18:18:49 -07001253 /**
1254 * Parse the given APK file, treating it as as a single monolithic package.
1255 * <p>
1256 * Note that this <em>does not</em> perform signature verification; that
1257 * must be done separately in {@link #collectCertificates(Package, int)}.
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001258 *
1259 * @deprecated external callers should move to
1260 * {@link #parsePackage(File, int)}. Eventually this method will
1261 * be marked private.
Jeff Sharkey275e0852014-06-17 18:18:49 -07001262 */
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001263 @Deprecated
Jeff Sharkey275e0852014-06-17 18:18:49 -07001264 public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
Fyodor Kupolov965fa692016-10-28 18:20:25 -07001265 final AssetManager assets = newConfiguredAssetManager();
Adam Lesinski4e862812016-11-21 16:02:24 -08001266 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001267 if (mOnlyCoreApps) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001268 if (!lite.coreApp) {
1269 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1270 "Not a coreApp: " + apkFile);
1271 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001272 }
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07001273
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001274 try {
1275 final Package pkg = parseBaseApk(apkFile, assets, flags);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001276 pkg.setCodePath(apkFile.getAbsolutePath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001277 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001278 return pkg;
1279 } finally {
1280 IoUtils.closeQuietly(assets);
1281 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001282 }
1283
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001284 private static int loadApkIntoAssetManager(AssetManager assets, String apkPath, int flags)
1285 throws PackageParserException {
1286 if ((flags & PARSE_MUST_BE_APK) != 0 && !isApkPath(apkPath)) {
1287 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1288 "Invalid package file: " + apkPath);
1289 }
1290
1291 // The AssetManager guarantees uniqueness for asset paths, so if this asset path
1292 // already exists in the AssetManager, addAssetPath will only return the cookie
1293 // assigned to it.
1294 int cookie = assets.addAssetPath(apkPath);
1295 if (cookie == 0) {
1296 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1297 "Failed adding asset path: " + apkPath);
1298 }
1299 return cookie;
1300 }
1301
1302 private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
1303 throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001304 final String apkPath = apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001305
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07001306 String volumeUuid = null;
1307 if (apkPath.startsWith(MNT_EXPAND)) {
1308 final int end = apkPath.indexOf('/', MNT_EXPAND.length());
1309 volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
1310 }
1311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001312 mParseError = PackageManager.INSTALL_SUCCEEDED;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001313 mArchiveSourcePath = apkFile.getAbsolutePath();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001314
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001315 if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001316
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001317 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
1318
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08001319 Resources res = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001320 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001321 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001322 res = new Resources(assets, mMetrics, null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001323 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
1324
1325 final String[] outError = new String[1];
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001326 final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001327 if (pkg == null) {
1328 throw new PackageParserException(mParseError,
1329 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001331
Svet Ganov354cd3c2015-12-17 11:35:04 -08001332 pkg.setVolumeUuid(volumeUuid);
1333 pkg.setApplicationVolumeUuid(volumeUuid);
1334 pkg.setBaseCodePath(apkPath);
1335 pkg.setSignatures(null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001336
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001337 return pkg;
1338
1339 } catch (PackageParserException e) {
1340 throw e;
1341 } catch (Exception e) {
1342 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001343 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001344 } finally {
1345 IoUtils.closeQuietly(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001347 }
1348
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001349 private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001350 throws PackageParserException {
1351 final String apkPath = pkg.splitCodePaths[splitIndex];
Jeff Sharkey275e0852014-06-17 18:18:49 -07001352
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001353 mParseError = PackageManager.INSTALL_SUCCEEDED;
1354 mArchiveSourcePath = apkPath;
1355
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001356 if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
1357
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001358 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
1359
Adam Lesinski4e862812016-11-21 16:02:24 -08001360 final Resources res;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001361 XmlResourceParser parser = null;
1362 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001363 res = new Resources(assets, mMetrics, null);
Romain Guy408afbf2017-01-25 10:23:03 -08001364 assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001365 Build.VERSION.RESOURCES_SDK_INT);
1366 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
1367
1368 final String[] outError = new String[1];
1369 pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
1370 if (pkg == null) {
1371 throw new PackageParserException(mParseError,
1372 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
1373 }
1374
1375 } catch (PackageParserException e) {
1376 throw e;
1377 } catch (Exception e) {
1378 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001379 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001380 } finally {
1381 IoUtils.closeQuietly(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001382 }
1383 }
1384
1385 /**
1386 * Parse the manifest of a <em>split APK</em>.
1387 * <p>
1388 * Note that split APKs have many more restrictions on what they're capable
1389 * of doing, so many valid features of a base APK have been carefully
1390 * omitted here.
1391 */
1392 private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001393 int splitIndex, String[] outError) throws XmlPullParserException, IOException,
1394 PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001395 AttributeSet attrs = parser;
1396
Jeff Sharkey78a13012014-07-15 20:18:34 -07001397 // We parsed manifest tag earlier; just skip past it
Svet Ganov354cd3c2015-12-17 11:35:04 -08001398 parsePackageSplitNames(parser, attrs);
Jeff Sharkey78a13012014-07-15 20:18:34 -07001399
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001400 mParseInstrumentationArgs = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001401
1402 int type;
1403
1404 boolean foundApp = false;
1405
1406 int outerDepth = parser.getDepth();
1407 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1408 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1409 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1410 continue;
1411 }
1412
1413 String tagName = parser.getName();
Adam Lesinski4e862812016-11-21 16:02:24 -08001414 if (tagName.equals(TAG_APPLICATION)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001415 if (foundApp) {
1416 if (RIGID_PARSER) {
1417 outError[0] = "<manifest> has more than one <application>";
1418 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1419 return null;
1420 } else {
1421 Slog.w(TAG, "<manifest> has more than one <application>");
1422 XmlUtils.skipCurrentTag(parser);
1423 continue;
1424 }
1425 }
1426
1427 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001428 if (!parseSplitApplication(pkg, res, parser, flags, splitIndex, outError)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001429 return null;
1430 }
1431
1432 } else if (RIGID_PARSER) {
1433 outError[0] = "Bad element under <manifest>: "
1434 + parser.getName();
1435 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1436 return null;
1437
1438 } else {
1439 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1440 + " at " + mArchiveSourcePath + " "
1441 + parser.getPositionDescription());
1442 XmlUtils.skipCurrentTag(parser);
1443 continue;
1444 }
1445 }
1446
1447 if (!foundApp) {
1448 outError[0] = "<manifest> does not contain an <application>";
1449 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1450 }
1451
1452 return pkg;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001453 }
1454
Todd Kennedy66c55532016-02-26 16:22:11 -08001455 public static int getApkSigningVersion(Package pkg) {
1456 try {
1457 if (ApkSignatureSchemeV2Verifier.hasSignature(pkg.baseCodePath)) {
1458 return APK_SIGNING_V2;
1459 }
1460 return APK_SIGNING_V1;
1461 } catch (IOException e) {
1462 }
1463 return APK_SIGNING_UNKNOWN;
1464 }
1465
Kenny Root6c918ce2013-04-02 14:04:24 -07001466 /**
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001467 * Populates the correct packages fields with the given certificates.
1468 * <p>
1469 * This is useful when we've already processed the certificates [such as during package
1470 * installation through an installer session]. We don't re-process the archive and
1471 * simply populate the correct fields.
1472 */
1473 public static void populateCertificates(Package pkg, Certificate[][] certificates)
1474 throws PackageParserException {
1475 pkg.mCertificates = null;
1476 pkg.mSignatures = null;
1477 pkg.mSigningKeys = null;
1478
1479 pkg.mCertificates = certificates;
1480 try {
1481 pkg.mSignatures = convertToSignatures(certificates);
1482 } catch (CertificateEncodingException e) {
1483 // certificates weren't encoded properly; something went wrong
1484 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1485 "Failed to collect certificates from " + pkg.baseCodePath, e);
1486 }
1487 pkg.mSigningKeys = new ArraySet<>(certificates.length);
1488 for (int i = 0; i < certificates.length; i++) {
1489 Certificate[] signerCerts = certificates[i];
1490 Certificate signerCert = signerCerts[0];
1491 pkg.mSigningKeys.add(signerCert.getPublicKey());
1492 }
1493 // add signatures to child packages
1494 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1495 for (int i = 0; i < childCount; i++) {
1496 Package childPkg = pkg.childPackages.get(i);
1497 childPkg.mCertificates = pkg.mCertificates;
1498 childPkg.mSignatures = pkg.mSignatures;
1499 childPkg.mSigningKeys = pkg.mSigningKeys;
1500 }
1501 }
1502
1503 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -07001504 * Collect certificates from all the APKs described in the given package,
Todd Kennedy373f0b42015-12-16 14:45:14 -08001505 * populating {@link Package#mSignatures}. Also asserts that all APK
Jeff Sharkey275e0852014-06-17 18:18:49 -07001506 * contents are signed correctly and consistently.
1507 */
Todd Kennedy66c55532016-02-26 16:22:11 -08001508 public static void collectCertificates(Package pkg, int parseFlags)
1509 throws PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001510 collectCertificatesInternal(pkg, parseFlags);
1511 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1512 for (int i = 0; i < childCount; i++) {
1513 Package childPkg = pkg.childPackages.get(i);
1514 childPkg.mCertificates = pkg.mCertificates;
1515 childPkg.mSignatures = pkg.mSignatures;
1516 childPkg.mSigningKeys = pkg.mSigningKeys;
1517 }
1518 }
1519
Todd Kennedy66c55532016-02-26 16:22:11 -08001520 private static void collectCertificatesInternal(Package pkg, int parseFlags)
1521 throws PackageParserException {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001522 pkg.mCertificates = null;
1523 pkg.mSignatures = null;
1524 pkg.mSigningKeys = null;
1525
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001526 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1527 try {
Todd Kennedyf720a9d2016-04-15 09:44:36 -07001528 collectCertificates(pkg, new File(pkg.baseCodePath), parseFlags);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001529
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001530 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
1531 for (int i = 0; i < pkg.splitCodePaths.length; i++) {
Todd Kennedyf720a9d2016-04-15 09:44:36 -07001532 collectCertificates(pkg, new File(pkg.splitCodePaths[i]), parseFlags);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001533 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001534 }
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001535 } finally {
1536 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001537 }
1538 }
1539
Todd Kennedyf720a9d2016-04-15 09:44:36 -07001540 private static void collectCertificates(Package pkg, File apkFile, int parseFlags)
Jeff Sharkey275e0852014-06-17 18:18:49 -07001541 throws PackageParserException {
1542 final String apkPath = apkFile.getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543
Alex Klyubine4157182016-01-05 13:27:05 -08001544 // Try to verify the APK using APK Signature Scheme v2.
1545 boolean verified = false;
1546 {
1547 Certificate[][] allSignersCerts = null;
1548 Signature[] signatures = null;
1549 try {
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001550 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV2");
Alex Klyubine4157182016-01-05 13:27:05 -08001551 allSignersCerts = ApkSignatureSchemeV2Verifier.verify(apkPath);
1552 signatures = convertToSignatures(allSignersCerts);
1553 // APK verified using APK Signature Scheme v2.
1554 verified = true;
1555 } catch (ApkSignatureSchemeV2Verifier.SignatureNotFoundException e) {
1556 // No APK Signature Scheme v2 signature found
Alex Klyubinabbc2bad2017-01-04 11:28:47 -08001557 if ((parseFlags & PARSE_IS_EPHEMERAL) != 0) {
1558 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1559 "No APK Signature Scheme v2 signature in ephemeral package " + apkPath,
1560 e);
1561 }
Svet Ganov67882122016-12-11 16:36:34 -08001562 // Static shared libraries must use only the V2 signing scheme
1563 if (pkg.applicationInfo.isStaticSharedLibrary()) {
1564 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1565 "Static shared libs must use v2 signature scheme " + apkPath);
1566 }
Alex Klyubine4157182016-01-05 13:27:05 -08001567 } catch (Exception e) {
1568 // APK Signature Scheme v2 signature was found but did not verify
1569 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1570 "Failed to collect certificates from " + apkPath
1571 + " using APK Signature Scheme v2",
1572 e);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001573 } finally {
1574 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Alex Klyubine4157182016-01-05 13:27:05 -08001575 }
1576
1577 if (verified) {
1578 if (pkg.mCertificates == null) {
1579 pkg.mCertificates = allSignersCerts;
1580 pkg.mSignatures = signatures;
1581 pkg.mSigningKeys = new ArraySet<>(allSignersCerts.length);
1582 for (int i = 0; i < allSignersCerts.length; i++) {
1583 Certificate[] signerCerts = allSignersCerts[i];
1584 Certificate signerCert = signerCerts[0];
1585 pkg.mSigningKeys.add(signerCert.getPublicKey());
1586 }
1587 } else {
1588 if (!Signature.areExactMatch(pkg.mSignatures, signatures)) {
1589 throw new PackageParserException(
1590 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
1591 apkPath + " has mismatched certificates");
1592 }
1593 }
1594 // Not yet done, because we need to confirm that AndroidManifest.xml exists and,
1595 // if requested, that classes.dex exists.
1596 }
1597 }
1598
Jeff Sharkey275e0852014-06-17 18:18:49 -07001599 StrictJarFile jarFile = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600 try {
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001601 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor");
Alex Klyubin9b59bc42016-03-24 12:02:20 -07001602 // Ignore signature stripping protections when verifying APKs from system partition.
1603 // For those APKs we only care about extracting signer certificates, and don't care
1604 // about verifying integrity.
1605 boolean signatureSchemeRollbackProtectionsEnforced =
Todd Kennedyd022ac22016-04-13 10:49:29 -07001606 (parseFlags & PARSE_IS_SYSTEM_DIR) == 0;
Alex Klyubine4157182016-01-05 13:27:05 -08001607 jarFile = new StrictJarFile(
1608 apkPath,
Alex Klyubin9b59bc42016-03-24 12:02:20 -07001609 !verified, // whether to verify JAR signature
1610 signatureSchemeRollbackProtectionsEnforced);
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001611 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001612
Jeff Sharkey275e0852014-06-17 18:18:49 -07001613 // Always verify manifest, regardless of source
1614 final ZipEntry manifestEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
1615 if (manifestEntry == null) {
1616 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1617 "Package " + apkPath + " has no manifest");
1618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619
Alex Klyubine4157182016-01-05 13:27:05 -08001620 // Optimization: early termination when APK already verified
1621 if (verified) {
Alex Klyubine4157182016-01-05 13:27:05 -08001622 return;
1623 }
1624
1625 // APK's integrity needs to be verified using JAR signature scheme.
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001626 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV1");
Jeff Sharkey275e0852014-06-17 18:18:49 -07001627 final List<ZipEntry> toVerify = new ArrayList<>();
1628 toVerify.add(manifestEntry);
1629
1630 // If we're parsing an untrusted package, verify all contents
Todd Kennedyd022ac22016-04-13 10:49:29 -07001631 if ((parseFlags & PARSE_IS_SYSTEM_DIR) == 0) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001632 final Iterator<ZipEntry> i = jarFile.iterator();
1633 while (i.hasNext()) {
1634 final ZipEntry entry = i.next();
1635
1636 if (entry.isDirectory()) continue;
Christopher Tatef3d939c2015-09-17 12:25:51 -07001637
1638 final String entryName = entry.getName();
1639 if (entryName.startsWith("META-INF/")) continue;
1640 if (entryName.equals(ANDROID_MANIFEST_FILENAME)) continue;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001641
1642 toVerify.add(entry);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001644 }
1645
1646 // Verify that entries are signed consistently with the first entry
1647 // we encountered. Note that for splits, certificates may have
1648 // already been populated during an earlier parse of a base APK.
1649 for (ZipEntry entry : toVerify) {
1650 final Certificate[][] entryCerts = loadCertificates(jarFile, entry);
1651 if (ArrayUtils.isEmpty(entryCerts)) {
1652 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1653 "Package " + apkPath + " has no certificates at entry "
1654 + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001655 }
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001656 final Signature[] entrySignatures = convertToSignatures(entryCerts);
Kenny Rootd2d29252011-08-08 11:27:57 -07001657
Jeff Sharkey275e0852014-06-17 18:18:49 -07001658 if (pkg.mCertificates == null) {
1659 pkg.mCertificates = entryCerts;
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001660 pkg.mSignatures = entrySignatures;
dcashman55b10782014-04-09 14:20:38 -07001661 pkg.mSigningKeys = new ArraySet<PublicKey>();
1662 for (int i=0; i < entryCerts.length; i++) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001663 pkg.mSigningKeys.add(entryCerts[i][0].getPublicKey());
Kenny Rootbcc954d2011-08-08 16:19:08 -07001664 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001665 } else {
Jeff Sharkeyec55ef02014-07-08 11:28:00 -07001666 if (!Signature.areExactMatch(pkg.mSignatures, entrySignatures)) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001667 throw new PackageParserException(
1668 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, "Package " + apkPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001669 + " has mismatched certificates at entry "
Jeff Sharkey275e0852014-06-17 18:18:49 -07001670 + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001671 }
1672 }
1673 }
Todd Kennedy27c24fb2015-09-17 16:49:25 -07001674 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeybc097552014-09-09 14:57:26 -07001675 } catch (GeneralSecurityException e) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001676 throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING,
1677 "Failed to collect certificates from " + apkPath, e);
Jeff Sharkeybc097552014-09-09 14:57:26 -07001678 } catch (IOException | RuntimeException e) {
1679 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
1680 "Failed to collect certificates from " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001681 } finally {
1682 closeQuietly(jarFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 }
1685
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001686 private static Signature[] convertToSignatures(Certificate[][] certs)
1687 throws CertificateEncodingException {
1688 final Signature[] res = new Signature[certs.length];
1689 for (int i = 0; i < certs.length; i++) {
1690 res[i] = new Signature(certs[i]);
1691 }
1692 return res;
1693 }
1694
Fyodor Kupolov965fa692016-10-28 18:20:25 -07001695 private static AssetManager newConfiguredAssetManager() {
1696 AssetManager assetManager = new AssetManager();
Romain Guy408afbf2017-01-25 10:23:03 -08001697 assetManager.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Fyodor Kupolov965fa692016-10-28 18:20:25 -07001698 Build.VERSION.RESOURCES_SDK_INT);
1699 return assetManager;
1700 }
1701
Jeff Sharkey275e0852014-06-17 18:18:49 -07001702 /**
1703 * Utility method that retrieves lightweight details about a single APK
1704 * file, including package name, split name, and install location.
1705 *
1706 * @param apkFile path to a single APK
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001707 * @param flags optional parse flags, such as
1708 * {@link #PARSE_COLLECT_CERTIFICATES}
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001709 */
Jeff Sharkey275e0852014-06-17 18:18:49 -07001710 public static ApkLite parseApkLite(File apkFile, int flags)
1711 throws PackageParserException {
1712 final String apkPath = apkFile.getAbsolutePath();
1713
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001714 AssetManager assets = null;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001715 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 try {
Adam Lesinski4e862812016-11-21 16:02:24 -08001717 assets = newConfiguredAssetManager();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001718 int cookie = assets.addAssetPath(apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001719 if (cookie == 0) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001720 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1721 "Failed to parse " + apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001722 }
1723
Kenny Root05ca4c92011-09-15 10:36:25 -07001724 final DisplayMetrics metrics = new DisplayMetrics();
1725 metrics.setToDefaults();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001726
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001727 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Kenny Root05ca4c92011-09-15 10:36:25 -07001728
Jeff Sharkey275e0852014-06-17 18:18:49 -07001729 final Signature[] signatures;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001730 final Certificate[][] certificates;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001731 if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
1732 // TODO: factor signature related items out of Package object
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001733 final Package tempPkg = new Package((String) null);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001734 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1735 try {
Alex Klyubinabbc2bad2017-01-04 11:28:47 -08001736 collectCertificates(tempPkg, apkFile, flags);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001737 } finally {
1738 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1739 }
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001740 signatures = tempPkg.mSignatures;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001741 certificates = tempPkg.mCertificates;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001742 } else {
1743 signatures = null;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001744 certificates = null;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001745 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001746
Jeff Sharkey275e0852014-06-17 18:18:49 -07001747 final AttributeSet attrs = parser;
Narayan Kamathf9419f02017-06-15 11:35:38 +01001748 return parseApkLite(apkPath, parser, attrs, signatures, certificates);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001749
1750 } catch (XmlPullParserException | IOException | RuntimeException e) {
Dianne Hackborn34041732017-01-31 15:27:13 -08001751 Slog.w(TAG, "Failed to parse " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001752 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1753 "Failed to parse " + apkPath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001754 } finally {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001755 IoUtils.closeQuietly(parser);
Adam Lesinski4e862812016-11-21 16:02:24 -08001756 IoUtils.closeQuietly(assets);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001757 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758 }
1759
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001760 private static String validateName(String name, boolean requireSeparator,
1761 boolean requireFilename) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 final int N = name.length();
1763 boolean hasSep = false;
1764 boolean front = true;
1765 for (int i=0; i<N; i++) {
1766 final char c = name.charAt(i);
1767 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1768 front = false;
1769 continue;
1770 }
1771 if (!front) {
1772 if ((c >= '0' && c <= '9') || c == '_') {
1773 continue;
1774 }
1775 }
1776 if (c == '.') {
1777 hasSep = true;
1778 front = true;
1779 continue;
1780 }
1781 return "bad character '" + c + "'";
1782 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001783 if (requireFilename && !FileUtils.isValidExtFilename(name)) {
1784 return "Invalid filename";
1785 }
1786 return hasSep || !requireSeparator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 ? null : "must have at least one '.' separator";
1788 }
1789
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001790 private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
Svet Ganov354cd3c2015-12-17 11:35:04 -08001791 AttributeSet attrs) throws IOException, XmlPullParserException,
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001792 PackageParserException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001793
1794 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001795 while ((type = parser.next()) != XmlPullParser.START_TAG
1796 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 }
1798
Kenny Rootd2d29252011-08-08 11:27:57 -07001799 if (type != XmlPullParser.START_TAG) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001800 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1801 "No start tag found");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001802 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001803 if (!parser.getName().equals(TAG_MANIFEST)) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001804 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1805 "No <manifest> tag");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001806 }
1807
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001808 final String packageName = attrs.getAttributeValue(null, "package");
1809 if (!"android".equals(packageName)) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001810 final String error = validateName(packageName, true, true);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001811 if (error != null) {
1812 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1813 "Invalid manifest package: " + error);
1814 }
1815 }
1816
Jeff Sharkey275e0852014-06-17 18:18:49 -07001817 String splitName = attrs.getAttributeValue(null, "split");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001818 if (splitName != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001819 if (splitName.length() == 0) {
1820 splitName = null;
1821 } else {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001822 final String error = validateName(splitName, false, false);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001823 if (error != null) {
1824 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1825 "Invalid manifest split: " + error);
1826 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001827 }
1828 }
1829
1830 return Pair.create(packageName.intern(),
1831 (splitName != null) ? splitName.intern() : splitName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 }
1833
Adam Lesinski4e862812016-11-21 16:02:24 -08001834 private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,
Narayan Kamathf9419f02017-06-15 11:35:38 +01001835 Signature[] signatures, Certificate[][] certificates)
Adam Lesinski4e862812016-11-21 16:02:24 -08001836 throws IOException, XmlPullParserException, PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001837 final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001838
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001839 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001840 int versionCode = 0;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001841 int revisionCode = 0;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001842 boolean coreApp = false;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001843 boolean debuggable = false;
Narayan Kamathff110bd2014-07-04 18:30:45 +01001844 boolean multiArch = false;
Selim Gurun2d291d82016-02-05 17:50:53 -08001845 boolean use32bitAbi = false;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001846 boolean extractNativeLibs = true;
Adam Lesinski4e862812016-11-21 16:02:24 -08001847 boolean isolatedSplits = false;
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001848 boolean isFeatureSplit = false;
1849 String configForSplit = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001850 String usesSplitName = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001851
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001852 for (int i = 0; i < attrs.getAttributeCount(); i++) {
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001853 final String attr = attrs.getAttributeName(i);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001854 if (attr.equals("installLocation")) {
1855 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001856 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001857 } else if (attr.equals("versionCode")) {
1858 versionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001859 } else if (attr.equals("revisionCode")) {
1860 revisionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001861 } else if (attr.equals("coreApp")) {
1862 coreApp = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski4e862812016-11-21 16:02:24 -08001863 } else if (attr.equals("isolatedSplits")) {
1864 isolatedSplits = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001865 } else if (attr.equals("configForSplit")) {
1866 configForSplit = attrs.getAttributeValue(i);
1867 } else if (attr.equals("isFeatureSplit")) {
1868 isFeatureSplit = attrs.getAttributeBooleanValue(i, false);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001869 }
1870 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001871
1872 // Only search the tree when the tag is directly below <manifest>
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001873 int type;
Kenny Root05ca4c92011-09-15 10:36:25 -07001874 final int searchDepth = parser.getDepth() + 1;
1875
1876 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
1877 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1878 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
1879 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1880 continue;
1881 }
1882
Adam Lesinski4e862812016-11-21 16:02:24 -08001883 if (parser.getDepth() != searchDepth) {
1884 continue;
1885 }
1886
1887 if (TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
1888 final VerifierInfo verifier = parseVerifier(attrs);
Kenny Root05ca4c92011-09-15 10:36:25 -07001889 if (verifier != null) {
1890 verifiers.add(verifier);
1891 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001892 } else if (TAG_APPLICATION.equals(parser.getName())) {
Narayan Kamatha8755a82014-07-15 12:26:35 +01001893 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1894 final String attr = attrs.getAttributeName(i);
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001895 if ("debuggable".equals(attr)) {
1896 debuggable = attrs.getAttributeBooleanValue(i, false);
1897 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001898 if ("multiArch".equals(attr)) {
1899 multiArch = attrs.getAttributeBooleanValue(i, false);
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001900 }
Selim Gurun2d291d82016-02-05 17:50:53 -08001901 if ("use32bitAbi".equals(attr)) {
1902 use32bitAbi = attrs.getAttributeBooleanValue(i, false);
Tao Baic9a02372016-01-12 15:02:24 -08001903 }
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001904 if ("extractNativeLibs".equals(attr)) {
1905 extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
Narayan Kamatha8755a82014-07-15 12:26:35 +01001906 }
1907 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001908 } else if (TAG_USES_SPLIT.equals(parser.getName())) {
1909 if (usesSplitName != null) {
1910 Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
1911 continue;
1912 }
1913
1914 usesSplitName = attrs.getAttributeValue(ANDROID_RESOURCES, "name");
1915 if (usesSplitName == null) {
1916 throw new PackageParserException(
1917 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1918 "<uses-split> tag requires 'android:name' attribute");
1919 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001920 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001921 }
1922
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001923 return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
1924 configForSplit, usesSplitName, versionCode, revisionCode, installLocation,
1925 verifiers, signatures, certificates, coreApp, debuggable, multiArch, use32bitAbi,
Narayan Kamath96c11c52017-08-09 13:07:21 +01001926 extractNativeLibs, isolatedSplits);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001927 }
1928
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001929 /**
Svet Ganov354cd3c2015-12-17 11:35:04 -08001930 * Parses a child package and adds it to the parent if successful. If you add
1931 * new tags that need to be supported by child packages make sure to add them
1932 * to {@link #CHILD_PACKAGE_TAGS}.
1933 *
1934 * @param parentPkg The parent that contains the child
1935 * @param res Resources against which to resolve values
1936 * @param parser Parser of the manifest
1937 * @param flags Flags about how to parse
1938 * @param outError Human readable error if parsing fails
1939 * @return True of parsing succeeded.
1940 *
1941 * @throws XmlPullParserException
1942 * @throws IOException
1943 */
1944 private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser,
1945 int flags, String[] outError) throws XmlPullParserException, IOException {
1946 // Let ppl not abuse this mechanism by limiting the packages per APK
1947 if (parentPkg.childPackages != null && parentPkg.childPackages.size() + 2
1948 > MAX_PACKAGES_PER_APK) {
1949 outError[0] = "Maximum number of packages per APK is: " + MAX_PACKAGES_PER_APK;
1950 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1951 return false;
1952 }
1953
1954 // Make sure we have a valid child package name
1955 String childPackageName = parser.getAttributeValue(null, "package");
1956 if (validateName(childPackageName, true, false) != null) {
1957 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1958 return false;
1959 }
1960
1961 // Child packages must be unique
1962 if (childPackageName.equals(parentPkg.packageName)) {
1963 String message = "Child package name cannot be equal to parent package name: "
1964 + parentPkg.packageName;
1965 Slog.w(TAG, message);
1966 outError[0] = message;
1967 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1968 return false;
1969 }
1970
1971 // Child packages must be unique
1972 if (parentPkg.hasChildPackage(childPackageName)) {
1973 String message = "Duplicate child package:" + childPackageName;
1974 Slog.w(TAG, message);
1975 outError[0] = message;
1976 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1977 return false;
1978 }
1979
1980 // Go ahead and parse the child
1981 Package childPkg = new Package(childPackageName);
1982
1983 // Child package inherits parent version code/name/target SDK
1984 childPkg.mVersionCode = parentPkg.mVersionCode;
1985 childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
1986 childPkg.mVersionName = parentPkg.mVersionName;
1987 childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
Todd Kennedy89d60182016-03-11 11:18:32 -08001988 childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001989
1990 childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
1991 if (childPkg == null) {
1992 // If we got null then error was set during child parsing
1993 return false;
1994 }
1995
1996 // Set the parent-child relation
1997 if (parentPkg.childPackages == null) {
1998 parentPkg.childPackages = new ArrayList<>();
1999 }
2000 parentPkg.childPackages.add(childPkg);
2001 childPkg.parentPackage = parentPkg;
2002
2003 return true;
2004 }
2005
2006 /**
2007 * Parse the manifest of a <em>base APK</em>. When adding new features you
2008 * need to consider whether they should be supported by split APKs and child
2009 * packages.
2010 *
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09002011 * @param apkPath The package apk file path
Svet Ganov354cd3c2015-12-17 11:35:04 -08002012 * @param res The resources from which to resolve values
2013 * @param parser The manifest parser
2014 * @param flags Flags how to parse
2015 * @param outError Human readable error message
2016 * @return Parsed package or null on error.
2017 *
2018 * @throws XmlPullParserException
2019 * @throws IOException
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002020 */
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09002021 private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002022 String[] outError) throws XmlPullParserException, IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07002023 final String splitName;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002024 final String pkgName;
2025
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07002026 try {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002027 Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07002028 pkgName = packageSplit.first;
2029 splitName = packageSplit.second;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002030
2031 if (!TextUtils.isEmpty(splitName)) {
2032 outError[0] = "Expected base APK, but found split " + splitName;
2033 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2034 return null;
2035 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07002036 } catch (PackageParserException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002037 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2038 return null;
2039 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07002040
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09002041 if (mCallback != null) {
2042 String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath);
2043 if (overlayPaths != null && overlayPaths.length > 0) {
2044 for (String overlayPath : overlayPaths) {
2045 res.getAssets().addOverlayPath(overlayPath);
2046 }
2047 }
2048 }
2049
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07002050 final Package pkg = new Package(pkgName);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07002051
Svet Ganov354cd3c2015-12-17 11:35:04 -08002052 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053 com.android.internal.R.styleable.AndroidManifest);
Svet Ganov354cd3c2015-12-17 11:35:04 -08002054
Dianne Hackborn8472e612014-01-23 17:57:20 -08002055 pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002056 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08002057 pkg.baseRevisionCode = sa.getInteger(
2058 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002059 pkg.mVersionName = sa.getNonConfigurationString(
2060 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002061 if (pkg.mVersionName != null) {
2062 pkg.mVersionName = pkg.mVersionName.intern();
2063 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002064
2065 pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
2066
2067 sa.recycle();
2068
2069 return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
2070 }
2071
2072 /**
2073 * This is the common parsing routing for handling parent and child
2074 * packages in a base APK. The difference between parent and child
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002075 * parsing is that some tags are not supported by child packages as
Svet Ganov354cd3c2015-12-17 11:35:04 -08002076 * well as some manifest attributes are ignored. The implementation
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002077 * assumes the calling code has already handled the manifest tag if needed
Svet Ganov354cd3c2015-12-17 11:35:04 -08002078 * (this applies to the parent only).
2079 *
2080 * @param pkg The package which to populate
2081 * @param acceptedTags Which tags to handle, null to handle all
2082 * @param res Resources against which to resolve values
2083 * @param parser Parser of the manifest
2084 * @param flags Flags about how to parse
2085 * @param outError Human readable error if parsing fails
2086 * @return The package if parsing succeeded or null.
2087 *
2088 * @throws XmlPullParserException
2089 * @throws IOException
2090 */
2091 private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
2092 XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
2093 IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002094 mParseInstrumentationArgs = null;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002095
2096 int type;
2097 boolean foundApp = false;
2098
2099 TypedArray sa = res.obtainAttributes(parser,
2100 com.android.internal.R.styleable.AndroidManifest);
2101
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002102 String str = sa.getNonConfigurationString(
2103 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
2104 if (str != null && str.length() > 0) {
Chad Brubaker32d07dc2016-12-01 15:30:01 -08002105 if ((flags & PARSE_IS_EPHEMERAL) != 0) {
2106 outError[0] = "sharedUserId not allowed in ephemeral application";
2107 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
2108 return null;
2109 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002110 String nameError = validateName(str, true, false);
Svet Ganov354cd3c2015-12-17 11:35:04 -08002111 if (nameError != null && !"android".equals(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002112 outError[0] = "<manifest> specifies bad sharedUserId name \""
2113 + str + "\": " + nameError;
2114 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
2115 return null;
2116 }
2117 pkg.mSharedUserId = str.intern();
2118 pkg.mSharedUserLabel = sa.getResourceId(
2119 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
2120 }
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -08002121
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08002122 pkg.installLocation = sa.getInteger(
2123 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07002124 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002125 pkg.applicationInfo.installLocation = pkg.installLocation;
Kenny Root7cb9be22012-05-30 15:30:37 -07002126
Todd Kennedy11e45072017-01-25 13:24:21 -08002127 final int targetSandboxVersion = sa.getInteger(
2128 com.android.internal.R.styleable.AndroidManifest_targetSandboxVersion,
2129 PARSE_DEFAULT_TARGET_SANDBOX);
2130 pkg.applicationInfo.targetSandboxVersion = targetSandboxVersion;
Alan Viverettefd274a02014-03-27 15:39:15 -07002131
Kenny Root7cb9be22012-05-30 15:30:37 -07002132 /* Set the global "forward lock" flag */
2133 if ((flags & PARSE_FORWARD_LOCK) != 0) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08002134 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
Kenny Root7cb9be22012-05-30 15:30:37 -07002135 }
2136
2137 /* Set the global "on SD card" flag */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07002138 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
Kenny Root7cb9be22012-05-30 15:30:37 -07002139 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
2140 }
2141
Adam Lesinski4e862812016-11-21 16:02:24 -08002142 if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) {
2143 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
2144 }
2145
Dianne Hackborn723738c2009-06-25 19:48:04 -07002146 // Resource boolean are -1, so 1 means we don't know the value.
2147 int supportsSmallScreens = 1;
2148 int supportsNormalScreens = 1;
2149 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002150 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002151 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002152 int anyDensity = 1;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002154 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -07002155 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2156 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2157 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002158 continue;
2159 }
2160
2161 String tagName = parser.getName();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002162
2163 if (acceptedTags != null && !acceptedTags.contains(tagName)) {
2164 Slog.w(TAG, "Skipping unsupported element under <manifest>: "
2165 + tagName + " at " + mArchiveSourcePath + " "
2166 + parser.getPositionDescription());
2167 XmlUtils.skipCurrentTag(parser);
2168 continue;
2169 }
2170
2171 if (tagName.equals(TAG_APPLICATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172 if (foundApp) {
2173 if (RIGID_PARSER) {
2174 outError[0] = "<manifest> has more than one <application>";
2175 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2176 return null;
2177 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002178 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002179 XmlUtils.skipCurrentTag(parser);
2180 continue;
2181 }
2182 }
2183
2184 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002185 if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186 return null;
2187 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002188 } else if (tagName.equals(TAG_OVERLAY)) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002189 sa = res.obtainAttributes(parser,
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002190 com.android.internal.R.styleable.AndroidManifestResourceOverlay);
2191 pkg.mOverlayTarget = sa.getString(
2192 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002193 pkg.mOverlayPriority = sa.getInt(
2194 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
2195 0);
Jaekyun Seok04342892017-03-02 15:24:19 +09002196 pkg.mIsStaticOverlay = sa.getBoolean(
2197 com.android.internal.R.styleable.AndroidManifestResourceOverlay_isStatic,
2198 false);
Todd Leeea2f3be2017-03-16 14:00:52 -07002199 final String propName = sa.getString(
2200 com.android.internal.R.styleable
2201 .AndroidManifestResourceOverlay_requiredSystemPropertyName);
2202 final String propValue = sa.getString(
2203 com.android.internal.R.styleable
2204 .AndroidManifestResourceOverlay_requiredSystemPropertyValue);
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002205 sa.recycle();
2206
2207 if (pkg.mOverlayTarget == null) {
2208 outError[0] = "<overlay> does not specify a target package";
2209 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2210 return null;
2211 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002212
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002213 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
2214 outError[0] = "<overlay> priority must be between 0 and 9999";
2215 mParseError =
2216 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2217 return null;
2218 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002219
2220 // check to see if overlay should be excluded based on system property condition
2221 if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
2222 Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and "
2223 + pkg.baseCodePath+ ": overlay ignored due to required system property: "
2224 + propName + " with value: " + propValue);
2225 return null;
Jaekyun Seok04342892017-03-02 15:24:19 +09002226 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002227
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002228 XmlUtils.skipCurrentTag(parser);
2229
Svet Ganov354cd3c2015-12-17 11:35:04 -08002230 } else if (tagName.equals(TAG_KEY_SETS)) {
2231 if (!parseKeySets(pkg, res, parser, outError)) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08002232 return null;
2233 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002234 } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002235 if (!parsePermissionGroup(pkg, flags, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002236 return null;
2237 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002238 } else if (tagName.equals(TAG_PERMISSION)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002239 if (!parsePermission(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002240 return null;
2241 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002242 } else if (tagName.equals(TAG_PERMISSION_TREE)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002243 if (!parsePermissionTree(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002244 return null;
2245 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002246 } else if (tagName.equals(TAG_USES_PERMISSION)) {
2247 if (!parseUsesPermission(pkg, res, parser)) {
Svetoslav96a77162015-04-03 13:58:33 -07002248 return null;
2249 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002250 } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
2251 || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
2252 if (!parseUsesPermission(pkg, res, parser)) {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002253 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002254 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002255 } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002256 ConfigurationInfo cPref = new ConfigurationInfo();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002257 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002258 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
2259 cPref.reqTouchScreen = sa.getInt(
2260 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
2261 Configuration.TOUCHSCREEN_UNDEFINED);
2262 cPref.reqKeyboardType = sa.getInt(
2263 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
2264 Configuration.KEYBOARD_UNDEFINED);
2265 if (sa.getBoolean(
2266 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
2267 false)) {
2268 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
2269 }
2270 cPref.reqNavigation = sa.getInt(
2271 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
2272 Configuration.NAVIGATION_UNDEFINED);
2273 if (sa.getBoolean(
2274 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
2275 false)) {
2276 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
2277 }
2278 sa.recycle();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002279 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002280
2281 XmlUtils.skipCurrentTag(parser);
2282
Svet Ganov354cd3c2015-12-17 11:35:04 -08002283 } else if (tagName.equals(TAG_USES_FEATURE)) {
2284 FeatureInfo fi = parseUsesFeature(res, parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002285 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
2286
Dianne Hackborn49237342009-08-27 20:08:01 -07002287 if (fi.name == null) {
2288 ConfigurationInfo cPref = new ConfigurationInfo();
2289 cPref.reqGlEsVersion = fi.reqGlEsVersion;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002290 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
Dianne Hackborn49237342009-08-27 20:08:01 -07002291 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07002292
2293 XmlUtils.skipCurrentTag(parser);
2294
Svet Ganov354cd3c2015-12-17 11:35:04 -08002295 } else if (tagName.equals(TAG_FEATURE_GROUP)) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002296 FeatureGroupInfo group = new FeatureGroupInfo();
2297 ArrayList<FeatureInfo> features = null;
2298 final int innerDepth = parser.getDepth();
2299 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2300 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
2301 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2302 continue;
2303 }
Adam Lesinski2c72b682014-06-24 09:56:01 -07002304
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002305 final String innerTagName = parser.getName();
2306 if (innerTagName.equals("uses-feature")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002307 FeatureInfo featureInfo = parseUsesFeature(res, parser);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002308 // FeatureGroups are stricter and mandate that
2309 // any <uses-feature> declared are mandatory.
2310 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
2311 features = ArrayUtils.add(features, featureInfo);
2312 } else {
2313 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
2314 " at " + mArchiveSourcePath + " " +
2315 parser.getPositionDescription());
2316 }
2317 XmlUtils.skipCurrentTag(parser);
2318 }
2319
2320 if (features != null) {
2321 group.features = new FeatureInfo[features.size()];
2322 group.features = features.toArray(group.features);
2323 }
2324 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
Adam Lesinski2c72b682014-06-24 09:56:01 -07002325
Svet Ganov354cd3c2015-12-17 11:35:04 -08002326 } else if (tagName.equals(TAG_USES_SDK)) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07002327 if (SDK_VERSION > 0) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002328 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002329 com.android.internal.R.styleable.AndroidManifestUsesSdk);
2330
Todd Kennedy4f657082016-06-28 10:31:05 -07002331 int minVers = 1;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002332 String minCode = null;
2333 int targetVers = 0;
2334 String targetCode = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002335
Dianne Hackborn851a5412009-05-08 12:06:44 -07002336 TypedValue val = sa.peekValue(
2337 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
2338 if (val != null) {
2339 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
2340 targetCode = minCode = val.string.toString();
2341 } else {
2342 // If it's not a string, it's an integer.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002343 targetVers = minVers = val.data;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002344 }
2345 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002346
Dianne Hackborn851a5412009-05-08 12:06:44 -07002347 val = sa.peekValue(
2348 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
2349 if (val != null) {
2350 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
Todd Kennedy89d60182016-03-11 11:18:32 -08002351 targetCode = val.string.toString();
2352 if (minCode == null) {
2353 minCode = targetCode;
2354 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002355 } else {
2356 // If it's not a string, it's an integer.
2357 targetVers = val.data;
2358 }
2359 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002361 sa.recycle();
2362
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002363 final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers, minCode,
2364 SDK_VERSION, SDK_CODENAMES, outError);
2365 if (minSdkVersion < 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002366 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2367 return null;
2368 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002369
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002370 final int targetSdkVersion = PackageParser.computeTargetSdkVersion(targetVers,
2371 targetCode, SDK_VERSION, SDK_CODENAMES, outError);
2372 if (targetSdkVersion < 0) {
2373 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2374 return null;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002375 }
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002376
2377 pkg.applicationInfo.minSdkVersion = minSdkVersion;
2378 pkg.applicationInfo.targetSdkVersion = targetSdkVersion;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002379 }
2380
2381 XmlUtils.skipCurrentTag(parser);
2382
Svet Ganov354cd3c2015-12-17 11:35:04 -08002383 } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
2384 sa = res.obtainAttributes(parser,
Dianne Hackborn723738c2009-06-25 19:48:04 -07002385 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
2386
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002387 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
2388 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
2389 0);
2390 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
2391 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
2392 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07002393 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
2394 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
2395 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002396
Dianne Hackborn723738c2009-06-25 19:48:04 -07002397 // This is a trick to get a boolean and still able to detect
2398 // if a value was actually set.
2399 supportsSmallScreens = sa.getInteger(
2400 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
2401 supportsSmallScreens);
2402 supportsNormalScreens = sa.getInteger(
2403 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
2404 supportsNormalScreens);
2405 supportsLargeScreens = sa.getInteger(
2406 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
2407 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002408 supportsXLargeScreens = sa.getInteger(
2409 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
2410 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002411 resizeable = sa.getInteger(
2412 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002413 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002414 anyDensity = sa.getInteger(
2415 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
2416 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07002417
2418 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002419
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07002420 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002421
Svet Ganov354cd3c2015-12-17 11:35:04 -08002422 } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
2423 sa = res.obtainAttributes(parser,
Dianne Hackborn854060af2009-07-09 18:14:31 -07002424 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
2425
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002426 // Note: don't allow this value to be a reference to a resource
2427 // that may change.
Dianne Hackborn854060af2009-07-09 18:14:31 -07002428 String name = sa.getNonResourceString(
2429 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
2430
2431 sa.recycle();
2432
2433 if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
2434 if (pkg.protectedBroadcasts == null) {
2435 pkg.protectedBroadcasts = new ArrayList<String>();
2436 }
2437 if (!pkg.protectedBroadcasts.contains(name)) {
2438 pkg.protectedBroadcasts.add(name.intern());
2439 }
2440 }
2441
2442 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002443
Svet Ganov354cd3c2015-12-17 11:35:04 -08002444 } else if (tagName.equals(TAG_INSTRUMENTATION)) {
2445 if (parseInstrumentation(pkg, res, parser, outError) == null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002446 return null;
2447 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002448 } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
2449 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002450 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2451
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002452 String orig =sa.getNonConfigurationString(
2453 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002454 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002455 if (pkg.mOriginalPackages == null) {
2456 pkg.mOriginalPackages = new ArrayList<String>();
2457 pkg.mRealPackage = pkg.packageName;
2458 }
2459 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002460 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002461
2462 sa.recycle();
2463
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002464 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002465
Svet Ganov354cd3c2015-12-17 11:35:04 -08002466 } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
2467 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002468 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2469
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002470 String name = sa.getNonConfigurationString(
2471 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002472
2473 sa.recycle();
2474
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002475 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002476 if (pkg.mAdoptPermissions == null) {
2477 pkg.mAdoptPermissions = new ArrayList<String>();
2478 }
2479 pkg.mAdoptPermissions.add(name);
2480 }
2481
2482 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002483
Svet Ganov354cd3c2015-12-17 11:35:04 -08002484 } else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002485 // Just skip this tag
2486 XmlUtils.skipCurrentTag(parser);
2487 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002488
Svet Ganov354cd3c2015-12-17 11:35:04 -08002489 } else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002490 // Just skip this tag
2491 XmlUtils.skipCurrentTag(parser);
2492 continue;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002493 } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
Michael Wrighteaeb1902013-09-05 18:15:57 -07002494 XmlUtils.skipCurrentTag(parser);
2495 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002496
Svet Ganov354cd3c2015-12-17 11:35:04 -08002497 } else if (tagName.equals(TAG_EAT_COMMENT)) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002498 // Just skip this tag
2499 XmlUtils.skipCurrentTag(parser);
2500 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002501
Svet Ganov354cd3c2015-12-17 11:35:04 -08002502 } else if (tagName.equals(TAG_PACKAGE)) {
Svet Ganova7532cf2016-05-02 08:13:17 -07002503 if (!MULTI_PACKAGE_APK_ENABLED) {
2504 XmlUtils.skipCurrentTag(parser);
2505 continue;
2506 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002507 if (!parseBaseApkChild(pkg, res, parser, flags, outError)) {
2508 // If parsing a child failed the error is already set
2509 return null;
2510 }
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002511
2512 } else if (tagName.equals(TAG_RESTRICT_UPDATE)) {
2513 if ((flags & PARSE_IS_SYSTEM_DIR) != 0) {
2514 sa = res.obtainAttributes(parser,
2515 com.android.internal.R.styleable.AndroidManifestRestrictUpdate);
2516 final String hash = sa.getNonConfigurationString(
2517 com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0);
2518 sa.recycle();
2519
2520 pkg.restrictUpdateHash = null;
2521 if (hash != null) {
2522 final int hashLength = hash.length();
2523 final byte[] hashBytes = new byte[hashLength / 2];
2524 for (int i = 0; i < hashLength; i += 2){
2525 hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4)
2526 + Character.digit(hash.charAt(i + 1), 16));
2527 }
2528 pkg.restrictUpdateHash = hashBytes;
2529 }
2530 }
2531
2532 XmlUtils.skipCurrentTag(parser);
2533
Dianne Hackborn854060af2009-07-09 18:14:31 -07002534 } else if (RIGID_PARSER) {
2535 outError[0] = "Bad element under <manifest>: "
2536 + parser.getName();
2537 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2538 return null;
2539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002540 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002541 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002542 + " at " + mArchiveSourcePath + " "
2543 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002544 XmlUtils.skipCurrentTag(parser);
2545 continue;
2546 }
2547 }
2548
2549 if (!foundApp && pkg.instrumentation.size() == 0) {
2550 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
2551 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
2552 }
2553
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002554 final int NP = PackageParser.NEW_PERMISSIONS.length;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002555 StringBuilder implicitPerms = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002556 for (int ip=0; ip<NP; ip++) {
2557 final PackageParser.NewPermissionInfo npi
2558 = PackageParser.NEW_PERMISSIONS[ip];
2559 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
2560 break;
2561 }
2562 if (!pkg.requestedPermissions.contains(npi.name)) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002563 if (implicitPerms == null) {
2564 implicitPerms = new StringBuilder(128);
2565 implicitPerms.append(pkg.packageName);
2566 implicitPerms.append(": compat added ");
2567 } else {
2568 implicitPerms.append(' ');
2569 }
2570 implicitPerms.append(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002571 pkg.requestedPermissions.add(npi.name);
2572 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002573 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002574 if (implicitPerms != null) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002575 Slog.i(TAG, implicitPerms.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002576 }
Dianne Hackborn79245122012-03-12 10:51:26 -07002577
2578 final int NS = PackageParser.SPLIT_PERMISSIONS.length;
2579 for (int is=0; is<NS; is++) {
2580 final PackageParser.SplitPermissionInfo spi
2581 = PackageParser.SPLIT_PERMISSIONS[is];
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -07002582 if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
2583 || !pkg.requestedPermissions.contains(spi.rootPerm)) {
Dianne Hackborn5e4705a2012-04-06 12:55:53 -07002584 continue;
Dianne Hackborn79245122012-03-12 10:51:26 -07002585 }
2586 for (int in=0; in<spi.newPerms.length; in++) {
2587 final String perm = spi.newPerms[in];
2588 if (!pkg.requestedPermissions.contains(perm)) {
2589 pkg.requestedPermissions.add(perm);
Dianne Hackborn79245122012-03-12 10:51:26 -07002590 }
2591 }
2592 }
2593
Dianne Hackborn723738c2009-06-25 19:48:04 -07002594 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
2595 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002596 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002597 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
2598 }
2599 if (supportsNormalScreens != 0) {
2600 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
2601 }
2602 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
2603 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002604 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002605 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
2606 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002607 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
2608 && pkg.applicationInfo.targetSdkVersion
2609 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
2610 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
2611 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002612 if (resizeable < 0 || (resizeable > 0
2613 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002614 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002615 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
2616 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002617 if (anyDensity < 0 || (anyDensity > 0
2618 && pkg.applicationInfo.targetSdkVersion
2619 >= android.os.Build.VERSION_CODES.DONUT)) {
2620 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07002621 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07002622
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002623 // At this point we can check if an application is not supporting densities and hence
2624 // cannot be windowed / resized. Note that an SDK version of 0 is common for
2625 // pre-Doughnut applications.
2626 if (pkg.applicationInfo.usesCompatibilityMode()) {
Winson Chungd3395382016-12-13 11:49:09 -08002627 adjustPackageToBeUnresizeableAndUnpipable(pkg);
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002628 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 return pkg;
2630 }
2631
Todd Leeea2f3be2017-03-16 14:00:52 -07002632 private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
2633
2634 if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
2635 if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
2636 // malformed condition - incomplete
2637 Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName
2638 + "=" + propValue + "' - require both requiredSystemPropertyName"
2639 + " AND requiredSystemPropertyValue to be specified.");
2640 return false;
2641 }
2642 // no valid condition set - so no exclusion criteria, overlay will be included.
2643 return true;
2644 }
2645
2646 // check property value - make sure it is both set and equal to expected value
2647 final String currValue = SystemProperties.get(propName);
2648 return (currValue != null && currValue.equals(propValue));
2649 }
2650
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002651 /**
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002652 * This is a pre-density application which will get scaled - instead of being pixel perfect.
2653 * This type of application is not resizable.
2654 *
2655 * @param pkg The package which needs to be marked as unresizable.
2656 */
Winson Chungd3395382016-12-13 11:49:09 -08002657 private void adjustPackageToBeUnresizeableAndUnpipable(Package pkg) {
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002658 for (Activity a : pkg.activities) {
2659 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -08002660 a.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE;
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002661 }
2662 }
2663
2664 /**
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002665 * Computes the targetSdkVersion to use at runtime. If the package is not
2666 * compatible with this platform, populates {@code outError[0]} with an
2667 * error message.
2668 * <p>
2669 * If {@code targetCode} is not specified, e.g. the value is {@code null},
2670 * then the {@code targetVers} will be returned unmodified.
2671 * <p>
2672 * Otherwise, the behavior varies based on whether the current platform
2673 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2674 * has length > 0:
2675 * <ul>
2676 * <li>If this is a pre-release platform and the value specified by
2677 * {@code targetCode} is contained within the array of allowed pre-release
2678 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2679 * <li>If this is a released platform, this method will return -1 to
2680 * indicate that the package is not compatible with this platform.
2681 * </ul>
2682 *
2683 * @param targetVers targetSdkVersion number, if specified in the
2684 * application manifest, or 0 otherwise
2685 * @param targetCode targetSdkVersion code, if specified in the application
2686 * manifest, or {@code null} otherwise
2687 * @param platformSdkVersion platform SDK version number, typically
2688 * Build.VERSION.SDK_INT
2689 * @param platformSdkCodenames array of allowed pre-release SDK codenames
2690 * for this platform
2691 * @param outError output array to populate with error, if applicable
2692 * @return the targetSdkVersion to use at runtime, or -1 if the package is
2693 * not compatible with this platform
2694 * @hide Exposed for unit testing only.
2695 */
2696 @TestApi
2697 public static int computeTargetSdkVersion(@IntRange(from = 0) int targetVers,
2698 @Nullable String targetCode, @IntRange(from = 1) int platformSdkVersion,
2699 @NonNull String[] platformSdkCodenames, @NonNull String[] outError) {
2700 // If it's a release SDK, return the version number unmodified.
2701 if (targetCode == null) {
2702 return targetVers;
2703 }
2704
2705 // If it's a pre-release SDK and the codename matches this platform, it
2706 // definitely targets this SDK.
2707 if (ArrayUtils.contains(platformSdkCodenames, targetCode)) {
2708 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2709 }
2710
2711 // Otherwise, we're looking at an incompatible pre-release SDK.
2712 if (platformSdkCodenames.length > 0) {
2713 outError[0] = "Requires development platform " + targetCode
2714 + " (current platform is any of "
2715 + Arrays.toString(platformSdkCodenames) + ")";
2716 } else {
2717 outError[0] = "Requires development platform " + targetCode
2718 + " but this is a release platform.";
2719 }
2720 return -1;
2721 }
2722
2723 /**
2724 * Computes the minSdkVersion to use at runtime. If the package is not
2725 * compatible with this platform, populates {@code outError[0]} with an
2726 * error message.
2727 * <p>
2728 * If {@code minCode} is not specified, e.g. the value is {@code null},
2729 * then behavior varies based on the {@code platformSdkVersion}:
2730 * <ul>
2731 * <li>If the platform SDK version is greater than or equal to the
2732 * {@code minVers}, returns the {@code mniVers} unmodified.
2733 * <li>Otherwise, returns -1 to indicate that the package is not
2734 * compatible with this platform.
2735 * </ul>
2736 * <p>
2737 * Otherwise, the behavior varies based on whether the current platform
2738 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2739 * has length > 0:
2740 * <ul>
2741 * <li>If this is a pre-release platform and the value specified by
2742 * {@code targetCode} is contained within the array of allowed pre-release
2743 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2744 * <li>If this is a released platform, this method will return -1 to
2745 * indicate that the package is not compatible with this platform.
2746 * </ul>
2747 *
2748 * @param minVers minSdkVersion number, if specified in the application
2749 * manifest, or 1 otherwise
2750 * @param minCode minSdkVersion code, if specified in the application
2751 * manifest, or {@code null} otherwise
2752 * @param platformSdkVersion platform SDK version number, typically
2753 * Build.VERSION.SDK_INT
2754 * @param platformSdkCodenames array of allowed prerelease SDK codenames
2755 * for this platform
2756 * @param outError output array to populate with error, if applicable
2757 * @return the minSdkVersion to use at runtime, or -1 if the package is not
2758 * compatible with this platform
2759 * @hide Exposed for unit testing only.
2760 */
2761 @TestApi
2762 public static int computeMinSdkVersion(@IntRange(from = 1) int minVers,
2763 @Nullable String minCode, @IntRange(from = 1) int platformSdkVersion,
2764 @NonNull String[] platformSdkCodenames, @NonNull String[] outError) {
2765 // If it's a release SDK, make sure we meet the minimum SDK requirement.
2766 if (minCode == null) {
2767 if (minVers <= platformSdkVersion) {
2768 return minVers;
2769 }
2770
2771 // We don't meet the minimum SDK requirement.
2772 outError[0] = "Requires newer sdk version #" + minVers
2773 + " (current version is #" + platformSdkVersion + ")";
2774 return -1;
2775 }
2776
2777 // If it's a pre-release SDK and the codename matches this platform, we
2778 // definitely meet the minimum SDK requirement.
2779 if (ArrayUtils.contains(platformSdkCodenames, minCode)) {
2780 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2781 }
2782
2783 // Otherwise, we're looking at an incompatible pre-release SDK.
2784 if (platformSdkCodenames.length > 0) {
2785 outError[0] = "Requires development platform " + minCode
2786 + " (current platform is any of "
2787 + Arrays.toString(platformSdkCodenames) + ")";
2788 } else {
2789 outError[0] = "Requires development platform " + minCode
2790 + " but this is a release platform.";
2791 }
2792 return -1;
2793 }
2794
Todd Kennedy27c24fb2015-09-17 16:49:25 -07002795 private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002796 FeatureInfo fi = new FeatureInfo();
2797 TypedArray sa = res.obtainAttributes(attrs,
2798 com.android.internal.R.styleable.AndroidManifestUsesFeature);
2799 // Note: don't allow this value to be a reference to a resource
2800 // that may change.
2801 fi.name = sa.getNonResourceString(
2802 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
Jeff Sharkey115d2c12016-02-15 17:25:57 -07002803 fi.version = sa.getInt(
2804 com.android.internal.R.styleable.AndroidManifestUsesFeature_version, 0);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002805 if (fi.name == null) {
2806 fi.reqGlEsVersion = sa.getInt(
2807 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
2808 FeatureInfo.GL_ES_VERSION_UNDEFINED);
2809 }
2810 if (sa.getBoolean(
2811 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) {
2812 fi.flags |= FeatureInfo.FLAG_REQUIRED;
2813 }
2814 sa.recycle();
2815 return fi;
2816 }
2817
Svet Ganov67882122016-12-11 16:36:34 -08002818 private boolean parseUsesStaticLibrary(Package pkg, Resources res, XmlResourceParser parser,
2819 String[] outError) throws XmlPullParserException, IOException {
2820 TypedArray sa = res.obtainAttributes(parser,
2821 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary);
2822
2823 // Note: don't allow this value to be a reference to a resource that may change.
2824 String lname = sa.getNonResourceString(
2825 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
2826 final int version = sa.getInt(
2827 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary_version, -1);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002828 String certSha256Digest = sa.getNonResourceString(com.android.internal.R.styleable
Svet Ganov67882122016-12-11 16:36:34 -08002829 .AndroidManifestUsesStaticLibrary_certDigest);
2830 sa.recycle();
2831
2832 // Since an APK providing a static shared lib can only provide the lib - fail if malformed
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002833 if (lname == null || version < 0 || certSha256Digest == null) {
Svet Ganov67882122016-12-11 16:36:34 -08002834 outError[0] = "Bad uses-static-library declaration name: " + lname + " version: "
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002835 + version + " certDigest" + certSha256Digest;
Svet Ganov67882122016-12-11 16:36:34 -08002836 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2837 XmlUtils.skipCurrentTag(parser);
2838 return false;
2839 }
2840
2841 // Can depend only on one version of the same library
2842 if (pkg.usesStaticLibraries != null && pkg.usesStaticLibraries.contains(lname)) {
2843 outError[0] = "Depending on multiple versions of static library " + lname;
2844 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2845 XmlUtils.skipCurrentTag(parser);
2846 return false;
2847 }
2848
2849 lname = lname.intern();
2850 // We allow ":" delimiters in the SHA declaration as this is the format
2851 // emitted by the certtool making it easy for developers to copy/paste.
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002852 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2853
2854 // Fot apps targeting O-MR1 we require explicit enumeration of all certs.
2855 String[] additionalCertSha256Digests = EmptyArray.STRING;
2856 if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.O) {
2857 additionalCertSha256Digests = parseAdditionalCertificates(res, parser, outError);
2858 if (additionalCertSha256Digests == null) {
2859 return false;
2860 }
2861 } else {
2862 XmlUtils.skipCurrentTag(parser);
2863 }
2864
2865 final String[] certSha256Digests = new String[additionalCertSha256Digests.length + 1];
2866 certSha256Digests[0] = certSha256Digest;
2867 System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests,
2868 1, additionalCertSha256Digests.length);
2869
Svet Ganov67882122016-12-11 16:36:34 -08002870 pkg.usesStaticLibraries = ArrayUtils.add(pkg.usesStaticLibraries, lname);
2871 pkg.usesStaticLibrariesVersions = ArrayUtils.appendInt(
Svet Ganov8a10ef52017-02-16 20:58:09 -08002872 pkg.usesStaticLibrariesVersions, version, true);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002873 pkg.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String[].class,
2874 pkg.usesStaticLibrariesCertDigests, certSha256Digests, true);
Svet Ganov67882122016-12-11 16:36:34 -08002875
2876 return true;
2877 }
2878
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002879 private String[] parseAdditionalCertificates(Resources resources, XmlResourceParser parser,
2880 String[] outError) throws XmlPullParserException, IOException {
2881 String[] certSha256Digests = EmptyArray.STRING;
2882
2883 int outerDepth = parser.getDepth();
2884 int type;
2885 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2886 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2887 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2888 continue;
2889 }
2890
2891 final String nodeName = parser.getName();
2892 if (nodeName.equals("additional-certificate")) {
2893 final TypedArray sa = resources.obtainAttributes(parser, com.android.internal.
2894 R.styleable.AndroidManifestAdditionalCertificate);
2895 String certSha256Digest = sa.getNonResourceString(com.android.internal.
2896 R.styleable.AndroidManifestAdditionalCertificate_certDigest);
2897 sa.recycle();
2898
2899 if (TextUtils.isEmpty(certSha256Digest)) {
2900 outError[0] = "Bad additional-certificate declaration with empty"
2901 + " certDigest:" + certSha256Digest;
2902 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2903 XmlUtils.skipCurrentTag(parser);
2904 sa.recycle();
2905 return null;
2906 }
2907
2908 // We allow ":" delimiters in the SHA declaration as this is the format
2909 // emitted by the certtool making it easy for developers to copy/paste.
2910 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2911 certSha256Digests = ArrayUtils.appendElement(String.class,
2912 certSha256Digests, certSha256Digest);
2913 } else {
2914 XmlUtils.skipCurrentTag(parser);
2915 }
2916 }
2917
2918 return certSha256Digests;
2919 }
2920
Svet Ganov354cd3c2015-12-17 11:35:04 -08002921 private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
2922 throws XmlPullParserException, IOException {
2923 TypedArray sa = res.obtainAttributes(parser,
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002924 com.android.internal.R.styleable.AndroidManifestUsesPermission);
2925
2926 // Note: don't allow this value to be a reference to a resource
2927 // that may change.
2928 String name = sa.getNonResourceString(
2929 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002930
Christopher Tatefb0676a2013-09-16 16:34:52 -07002931 int maxSdkVersion = 0;
2932 TypedValue val = sa.peekValue(
2933 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
2934 if (val != null) {
2935 if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
2936 maxSdkVersion = val.data;
2937 }
2938 }
2939
Dianne Hackborncd154e92017-02-28 17:37:35 -08002940 final String requiredFeature = sa.getNonConfigurationString(
2941 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredFeature, 0);
2942
2943 final String requiredNotfeature = sa.getNonConfigurationString(
2944 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);
2945
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002946 sa.recycle();
2947
Dianne Hackborncd154e92017-02-28 17:37:35 -08002948 XmlUtils.skipCurrentTag(parser);
2949
2950 if (name == null) {
2951 return true;
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002952 }
2953
Dianne Hackborncd154e92017-02-28 17:37:35 -08002954 if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) {
2955 return true;
2956 }
2957
2958 // Only allow requesting this permission if the platform supports the given feature.
2959 if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(requiredFeature)) {
2960 return true;
2961 }
2962
2963 // Only allow requesting this permission if the platform doesn't support the given feature.
2964 if (requiredNotfeature != null && mCallback != null
2965 && mCallback.hasFeature(requiredNotfeature)) {
2966 return true;
2967 }
2968
2969 int index = pkg.requestedPermissions.indexOf(name);
2970 if (index == -1) {
2971 pkg.requestedPermissions.add(name.intern());
2972 } else {
2973 Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
2974 + name + " in package: " + pkg.packageName + " at: "
2975 + parser.getPositionDescription());
2976 }
2977
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002978 return true;
2979 }
2980
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002981 private static String buildClassName(String pkg, CharSequence clsSeq,
2982 String[] outError) {
2983 if (clsSeq == null || clsSeq.length() <= 0) {
2984 outError[0] = "Empty class name in package " + pkg;
2985 return null;
2986 }
2987 String cls = clsSeq.toString();
2988 char c = cls.charAt(0);
2989 if (c == '.') {
Narayan Kamath07ac1442017-02-10 15:08:07 +00002990 return pkg + cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002991 }
2992 if (cls.indexOf('.') < 0) {
2993 StringBuilder b = new StringBuilder(pkg);
2994 b.append('.');
2995 b.append(cls);
Narayan Kamath07ac1442017-02-10 15:08:07 +00002996 return b.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002997 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002998 return cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002999 }
3000
3001 private static String buildCompoundName(String pkg,
3002 CharSequence procSeq, String type, String[] outError) {
3003 String proc = procSeq.toString();
3004 char c = proc.charAt(0);
3005 if (pkg != null && c == ':') {
3006 if (proc.length() < 2) {
3007 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
3008 + ": must be at least two characters";
3009 return null;
3010 }
3011 String subName = proc.substring(1);
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07003012 String nameError = validateName(subName, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003013 if (nameError != null) {
3014 outError[0] = "Invalid " + type + " name " + proc + " in package "
3015 + pkg + ": " + nameError;
3016 return null;
3017 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00003018 return pkg + proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003019 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07003020 String nameError = validateName(proc, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003021 if (nameError != null && !"system".equals(proc)) {
3022 outError[0] = "Invalid " + type + " name " + proc + " in package "
3023 + pkg + ": " + nameError;
3024 return null;
3025 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00003026 return proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003027 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003029 private static String buildProcessName(String pkg, String defProc,
3030 CharSequence procSeq, int flags, String[] separateProcesses,
3031 String[] outError) {
3032 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
3033 return defProc != null ? defProc : pkg;
3034 }
3035 if (separateProcesses != null) {
3036 for (int i=separateProcesses.length-1; i>=0; i--) {
3037 String sp = separateProcesses[i];
3038 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
3039 return pkg;
3040 }
3041 }
3042 }
3043 if (procSeq == null || procSeq.length() <= 0) {
3044 return defProc;
3045 }
Makoto Onuki812d188a2017-08-07 09:58:23 -07003046 return TextUtils.safeIntern(buildCompoundName(pkg, procSeq, "process", outError));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003047 }
3048
3049 private static String buildTaskAffinityName(String pkg, String defProc,
3050 CharSequence procSeq, String[] outError) {
3051 if (procSeq == null) {
3052 return defProc;
3053 }
3054 if (procSeq.length() <= 0) {
3055 return null;
3056 }
3057 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
3058 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003059
dcashman989eb3712014-06-17 12:56:12 -07003060 private boolean parseKeySets(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003061 XmlResourceParser parser, String[] outError)
Geremy Condraf1bcca82013-01-07 22:35:24 -08003062 throws XmlPullParserException, IOException {
dcashman989eb3712014-06-17 12:56:12 -07003063 // we've encountered the 'key-sets' tag
Geremy Condraf1bcca82013-01-07 22:35:24 -08003064 // all the keys and keysets that we want must be defined here
3065 // so we're going to iterate over the parser and pull out the things we want
3066 int outerDepth = parser.getDepth();
dcashman989eb3712014-06-17 12:56:12 -07003067 int currentKeySetDepth = -1;
Geremy Condraf1bcca82013-01-07 22:35:24 -08003068 int type;
dcashman989eb3712014-06-17 12:56:12 -07003069 String currentKeySet = null;
3070 ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
3071 ArraySet<String> upgradeKeySets = new ArraySet<String>();
3072 ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
3073 ArraySet<String> improperKeySets = new ArraySet<String>();
Geremy Condraf1bcca82013-01-07 22:35:24 -08003074 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3075 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
3076 if (type == XmlPullParser.END_TAG) {
dcashman989eb3712014-06-17 12:56:12 -07003077 if (parser.getDepth() == currentKeySetDepth) {
3078 currentKeySet = null;
3079 currentKeySetDepth = -1;
Kenny Root37dca152013-07-10 14:01:49 -07003080 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003081 continue;
3082 }
dcashman989eb3712014-06-17 12:56:12 -07003083 String tagName = parser.getName();
3084 if (tagName.equals("key-set")) {
3085 if (currentKeySet != null) {
dcashman5db0cd42015-05-22 15:24:40 -07003086 outError[0] = "Improperly nested 'key-set' tag at "
3087 + parser.getPositionDescription();
3088 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003089 return false;
3090 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08003091 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003092 com.android.internal.R.styleable.AndroidManifestKeySet);
3093 final String keysetName = sa.getNonResourceString(
3094 com.android.internal.R.styleable.AndroidManifestKeySet_name);
3095 definedKeySets.put(keysetName, new ArraySet<String>());
3096 currentKeySet = keysetName;
3097 currentKeySetDepth = parser.getDepth();
3098 sa.recycle();
3099 } else if (tagName.equals("public-key")) {
3100 if (currentKeySet == null) {
dcashman5db0cd42015-05-22 15:24:40 -07003101 outError[0] = "Improperly nested 'key-set' tag at "
3102 + parser.getPositionDescription();
3103 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003104 return false;
3105 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08003106 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003107 com.android.internal.R.styleable.AndroidManifestPublicKey);
3108 final String publicKeyName = sa.getNonResourceString(
3109 com.android.internal.R.styleable.AndroidManifestPublicKey_name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003110 final String encodedKey = sa.getNonResourceString(
dcashman989eb3712014-06-17 12:56:12 -07003111 com.android.internal.R.styleable.AndroidManifestPublicKey_value);
3112 if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
dcashman5db0cd42015-05-22 15:24:40 -07003113 outError[0] = "'public-key' " + publicKeyName + " must define a public-key value"
3114 + " on first use at " + parser.getPositionDescription();
3115 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Kenny Root37dca152013-07-10 14:01:49 -07003116 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003117 return false;
3118 } else if (encodedKey != null) {
3119 PublicKey currentKey = parsePublicKey(encodedKey);
3120 if (currentKey == null) {
3121 Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
3122 + parser.getPositionDescription() + " key-set " + currentKeySet
3123 + " will not be added to the package's defined key-sets.");
3124 sa.recycle();
3125 improperKeySets.add(currentKeySet);
3126 XmlUtils.skipCurrentTag(parser);
3127 continue;
3128 }
3129 if (publicKeys.get(publicKeyName) == null
3130 || publicKeys.get(publicKeyName).equals(currentKey)) {
3131
3132 /* public-key first definition, or matches old definition */
3133 publicKeys.put(publicKeyName, currentKey);
3134 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003135 outError[0] = "Value of 'public-key' " + publicKeyName
dcashman989eb3712014-06-17 12:56:12 -07003136 + " conflicts with previously defined value at "
dcashman5db0cd42015-05-22 15:24:40 -07003137 + parser.getPositionDescription();
3138 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003139 sa.recycle();
3140 return false;
3141 }
Kenny Root37dca152013-07-10 14:01:49 -07003142 }
dcashman989eb3712014-06-17 12:56:12 -07003143 definedKeySets.get(currentKeySet).add(publicKeyName);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003144 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003145 XmlUtils.skipCurrentTag(parser);
3146 } else if (tagName.equals("upgrade-key-set")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003147 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003148 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
3149 String name = sa.getNonResourceString(
3150 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
3151 upgradeKeySets.add(name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003152 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003153 XmlUtils.skipCurrentTag(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003154 } else if (RIGID_PARSER) {
dcashman5db0cd42015-05-22 15:24:40 -07003155 outError[0] = "Bad element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003156 + " at " + mArchiveSourcePath + " "
dcashman5db0cd42015-05-22 15:24:40 -07003157 + parser.getPositionDescription();
3158 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Geremy Condraf1bcca82013-01-07 22:35:24 -08003159 return false;
3160 } else {
dcashman989eb3712014-06-17 12:56:12 -07003161 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003162 + " at " + mArchiveSourcePath + " "
3163 + parser.getPositionDescription());
3164 XmlUtils.skipCurrentTag(parser);
3165 continue;
3166 }
3167 }
dcashman989eb3712014-06-17 12:56:12 -07003168 Set<String> publicKeyNames = publicKeys.keySet();
3169 if (publicKeyNames.removeAll(definedKeySets.keySet())) {
dcashman5db0cd42015-05-22 15:24:40 -07003170 outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
3171 + "'key-set' and 'public-key' names must be distinct.";
3172 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003173 return false;
3174 }
3175 owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
3176 for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) {
3177 final String keySetName = e.getKey();
3178 if (e.getValue().size() == 0) {
3179 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3180 + "'key-set' " + keySetName + " has no valid associated 'public-key'."
3181 + " Not including in package's defined key-sets.");
3182 continue;
3183 } else if (improperKeySets.contains(keySetName)) {
3184 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3185 + "'key-set' " + keySetName + " contained improper 'public-key'"
3186 + " tags. Not including in package's defined key-sets.");
3187 continue;
3188 }
3189 owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
3190 for (String s : e.getValue()) {
3191 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
Geremy Condraf1bcca82013-01-07 22:35:24 -08003192 }
3193 }
dcashman989eb3712014-06-17 12:56:12 -07003194 if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
3195 owner.mUpgradeKeySets = upgradeKeySets;
3196 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003197 outError[0] ="Package" + owner.packageName + " AndroidManifext.xml "
3198 + "does not define all 'upgrade-key-set's .";
3199 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003200 return false;
3201 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003202 return true;
3203 }
3204
Dianne Hackborncd154e92017-02-28 17:37:35 -08003205 private boolean parsePermissionGroup(Package owner, int flags, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003206 XmlResourceParser parser, String[] outError)
3207 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003208 PermissionGroup perm = new PermissionGroup(owner);
3209
Svet Ganov354cd3c2015-12-17 11:35:04 -08003210 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003211 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003212 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003213 "<permission-group>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003214 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
3215 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003216 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003217 com.android.internal.R.styleable.AndroidManifestPermissionGroup_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003218 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
3219 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003220 sa.recycle();
3221 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003222 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003223 }
3224
3225 perm.info.descriptionRes = sa.getResourceId(
3226 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
3227 0);
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003228 perm.info.requestRes = sa.getResourceId(
3229 com.android.internal.R.styleable.AndroidManifestPermissionGroup_request, 0);
Dianne Hackborn7454d3b2012-09-12 17:22:00 -07003230 perm.info.flags = sa.getInt(
3231 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07003232 perm.info.priority = sa.getInt(
3233 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
Dianne Hackborn99222d22012-05-06 16:30:15 -07003234 if (perm.info.priority > 0 && (flags&PARSE_IS_SYSTEM) == 0) {
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07003235 perm.info.priority = 0;
3236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003237
3238 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003239
Svet Ganov354cd3c2015-12-17 11:35:04 -08003240 if (!parseAllMetaData(res, parser, "<permission-group>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003241 outError)) {
3242 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003243 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003244 }
3245
3246 owner.permissionGroups.add(perm);
3247
Dianne Hackborncd154e92017-02-28 17:37:35 -08003248 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003249 }
3250
Dianne Hackborncd154e92017-02-28 17:37:35 -08003251 private boolean parsePermission(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003252 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003253 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003254
Svet Ganov354cd3c2015-12-17 11:35:04 -08003255 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003256 com.android.internal.R.styleable.AndroidManifestPermission);
3257
Dianne Hackborncd154e92017-02-28 17:37:35 -08003258 Permission perm = new Permission(owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003259 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003260 "<permission>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003261 com.android.internal.R.styleable.AndroidManifestPermission_name,
3262 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003263 com.android.internal.R.styleable.AndroidManifestPermission_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003264 com.android.internal.R.styleable.AndroidManifestPermission_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003265 com.android.internal.R.styleable.AndroidManifestPermission_logo,
3266 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003267 sa.recycle();
3268 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003269 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 }
3271
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003272 // Note: don't allow this value to be a reference to a resource
3273 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003274 perm.info.group = sa.getNonResourceString(
3275 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
3276 if (perm.info.group != null) {
3277 perm.info.group = perm.info.group.intern();
3278 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003280 perm.info.descriptionRes = sa.getResourceId(
3281 com.android.internal.R.styleable.AndroidManifestPermission_description,
3282 0);
3283
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003284 perm.info.requestRes = sa.getResourceId(
3285 com.android.internal.R.styleable.AndroidManifestPermission_request, 0);
3286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003287 perm.info.protectionLevel = sa.getInt(
3288 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
3289 PermissionInfo.PROTECTION_NORMAL);
3290
Dianne Hackborn2ca2c872012-09-16 16:03:36 -07003291 perm.info.flags = sa.getInt(
3292 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
3293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003294 sa.recycle();
Dianne Hackborne639da72012-02-21 15:11:13 -08003295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003296 if (perm.info.protectionLevel == -1) {
3297 outError[0] = "<permission> does not specify protectionLevel";
3298 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003299 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003300 }
Dianne Hackborne639da72012-02-21 15:11:13 -08003301
3302 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
3303
3304 if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_FLAGS) != 0) {
Todd Kennedyc247fa12017-06-02 10:29:22 -07003305 if ( (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_INSTANT) == 0
Chad Brubakera5d70a12017-03-23 11:04:50 -07003306 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0
Chad Brubakerc19706a2016-10-13 15:44:59 -07003307 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
Dianne Hackborne639da72012-02-21 15:11:13 -08003308 PermissionInfo.PROTECTION_SIGNATURE) {
Todd Kennedyc247fa12017-06-02 10:29:22 -07003309 outError[0] = "<permission> protectionLevel specifies a non-instnat flag but is "
Dianne Hackborne639da72012-02-21 15:11:13 -08003310 + "not based on signature type";
3311 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003312 return false;
Dianne Hackborne639da72012-02-21 15:11:13 -08003313 }
3314 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003315
Svet Ganov354cd3c2015-12-17 11:35:04 -08003316 if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003317 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003318 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 }
3320
3321 owner.permissions.add(perm);
3322
Dianne Hackborncd154e92017-02-28 17:37:35 -08003323 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 }
3325
Dianne Hackborncd154e92017-02-28 17:37:35 -08003326 private boolean parsePermissionTree(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003327 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003328 throws XmlPullParserException, IOException {
3329 Permission perm = new Permission(owner);
3330
Svet Ganov354cd3c2015-12-17 11:35:04 -08003331 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003332 com.android.internal.R.styleable.AndroidManifestPermissionTree);
3333
3334 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003335 "<permission-tree>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003336 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
3337 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003338 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003339 com.android.internal.R.styleable.AndroidManifestPermissionTree_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003340 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
3341 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003342 sa.recycle();
3343 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003344 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003345 }
3346
3347 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003349 int index = perm.info.name.indexOf('.');
3350 if (index > 0) {
3351 index = perm.info.name.indexOf('.', index+1);
3352 }
3353 if (index < 0) {
3354 outError[0] = "<permission-tree> name has less than three segments: "
3355 + perm.info.name;
3356 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003357 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003358 }
3359
3360 perm.info.descriptionRes = 0;
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003361 perm.info.requestRes = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003362 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
3363 perm.tree = true;
3364
Svet Ganov354cd3c2015-12-17 11:35:04 -08003365 if (!parseAllMetaData(res, parser, "<permission-tree>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003366 outError)) {
3367 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003368 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003369 }
3370
3371 owner.permissions.add(perm);
3372
Dianne Hackborncd154e92017-02-28 17:37:35 -08003373 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003374 }
3375
3376 private Instrumentation parseInstrumentation(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003377 XmlResourceParser parser, String[] outError)
3378 throws XmlPullParserException, IOException {
3379 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003380 com.android.internal.R.styleable.AndroidManifestInstrumentation);
3381
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003382 if (mParseInstrumentationArgs == null) {
3383 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
3384 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
3385 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003386 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003387 com.android.internal.R.styleable.AndroidManifestInstrumentation_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003388 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
3389 com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003390 mParseInstrumentationArgs.tag = "<instrumentation>";
3391 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003392
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003393 mParseInstrumentationArgs.sa = sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003394
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003395 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
3396 new InstrumentationInfo());
3397 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003398 sa.recycle();
3399 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3400 return null;
3401 }
3402
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003403 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003404 // Note: don't allow this value to be a reference to a resource
3405 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003406 str = sa.getNonResourceString(
3407 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
3408 a.info.targetPackage = str != null ? str.intern() : null;
3409
Dianne Hackborn34041732017-01-31 15:27:13 -08003410 str = sa.getNonResourceString(
Dianne Hackborn1be53542017-04-28 13:36:00 -07003411 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetProcesses);
3412 a.info.targetProcesses = str != null ? str.intern() : null;
Dianne Hackborn34041732017-01-31 15:27:13 -08003413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003414 a.info.handleProfiling = sa.getBoolean(
3415 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
3416 false);
3417
3418 a.info.functionalTest = sa.getBoolean(
3419 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
3420 false);
3421
3422 sa.recycle();
3423
3424 if (a.info.targetPackage == null) {
3425 outError[0] = "<instrumentation> does not specify targetPackage";
3426 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3427 return null;
3428 }
3429
Svet Ganov354cd3c2015-12-17 11:35:04 -08003430 if (!parseAllMetaData(res, parser, "<instrumentation>", a,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003431 outError)) {
3432 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3433 return null;
3434 }
3435
3436 owner.instrumentation.add(a);
3437
3438 return a;
3439 }
3440
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003441 /**
3442 * Parse the {@code application} XML tree at the current parse location in a
3443 * <em>base APK</em> manifest.
3444 * <p>
3445 * When adding new features, carefully consider if they should also be
3446 * supported by split APKs.
3447 */
3448 private boolean parseBaseApplication(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003449 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003450 throws XmlPullParserException, IOException {
3451 final ApplicationInfo ai = owner.applicationInfo;
3452 final String pkgName = owner.applicationInfo.packageName;
3453
Svet Ganov354cd3c2015-12-17 11:35:04 -08003454 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003455 com.android.internal.R.styleable.AndroidManifestApplication);
3456
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003457 if (!parsePackageItemInfo(owner, ai, outError,
3458 "<application>", sa, false /*nameRequired*/,
3459 com.android.internal.R.styleable.AndroidManifestApplication_name,
3460 com.android.internal.R.styleable.AndroidManifestApplication_label,
3461 com.android.internal.R.styleable.AndroidManifestApplication_icon,
3462 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon,
3463 com.android.internal.R.styleable.AndroidManifestApplication_logo,
3464 com.android.internal.R.styleable.AndroidManifestApplication_banner)) {
3465 sa.recycle();
3466 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3467 return false;
3468 }
3469
3470 if (ai.name != null) {
Todd Kennedyafb52692016-08-22 15:44:00 -07003471 ai.className = ai.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003472 }
3473
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003474 String manageSpaceActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003475 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
3476 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003477 if (manageSpaceActivity != null) {
3478 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
3479 outError);
3480 }
3481
Christopher Tate181fafa2009-05-14 11:12:14 -07003482 boolean allowBackup = sa.getBoolean(
3483 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
3484 if (allowBackup) {
3485 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07003486
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003487 // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
3488 // and restoreAnyVersion are only relevant if backup is possible for the
3489 // given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003490 String backupAgent = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003491 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
3492 Configuration.NATIVE_CONFIG_VERSION);
Christopher Tate181fafa2009-05-14 11:12:14 -07003493 if (backupAgent != null) {
3494 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07003495 if (DEBUG_BACKUP) {
3496 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003497 + " from " + pkgName + "+" + backupAgent);
3498 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003499
3500 if (sa.getBoolean(
3501 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
3502 true)) {
3503 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
3504 }
3505 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08003506 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
3507 false)) {
3508 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
3509 }
Christopher Tated1de2562014-06-17 17:12:35 -07003510 if (sa.getBoolean(
3511 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
3512 false)) {
3513 ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
3514 }
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003515 if (sa.getBoolean(
3516 com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
3517 false)) {
3518 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
3519 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003520 }
Matthew Williams303650c2015-04-17 18:22:51 -07003521
3522 TypedValue v = sa.peekValue(
3523 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
3524 if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
3525 if (DEBUG_BACKUP) {
3526 Slog.v(TAG, "fullBackupContent specified as boolean=" +
3527 (v.data == 0 ? "false" : "true"));
3528 }
3529 // "false" => -1, "true" => 0
3530 ai.fullBackupContent = (v.data == 0 ? -1 : 0);
3531 }
3532 if (DEBUG_BACKUP) {
3533 Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
3534 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003535 }
Christopher Tate4a627c72011-04-01 14:43:32 -07003536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003537 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08003538 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003539 ai.descriptionRes = sa.getResourceId(
3540 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
3541
3542 if ((flags&PARSE_IS_SYSTEM) != 0) {
3543 if (sa.getBoolean(
3544 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
3545 false)) {
Martijn Coenen441d61b2017-04-12 13:52:40 -07003546 // Check if persistence is based on a feature being present
3547 final String requiredFeature = sa.getNonResourceString(
Martijn Coenen8d74ca42017-04-28 09:41:48 -07003548 com.android.internal.R.styleable.
3549 AndroidManifestApplication_persistentWhenFeatureAvailable);
Martijn Coenen441d61b2017-04-12 13:52:40 -07003550 if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
3551 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
3552 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003553 }
Amith Yamasani0d8750d2013-05-01 15:25:28 -07003554 }
3555
3556 if (sa.getBoolean(
3557 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
3558 false)) {
3559 owner.mRequiredForAllUsers = true;
Amith Yamasanie993ae12013-04-15 13:42:57 -07003560 }
3561
3562 String restrictedAccountType = sa.getString(com.android.internal.R.styleable
3563 .AndroidManifestApplication_restrictedAccountType);
3564 if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
3565 owner.mRestrictedAccountType = restrictedAccountType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003566 }
3567
Amith Yamasaniccbe3892013-04-12 17:52:42 -07003568 String requiredAccountType = sa.getString(com.android.internal.R.styleable
3569 .AndroidManifestApplication_requiredAccountType);
3570 if (requiredAccountType != null && requiredAccountType.length() > 0) {
3571 owner.mRequiredAccountType = requiredAccountType;
3572 }
3573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003574 if (sa.getBoolean(
3575 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
3576 false)) {
3577 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
3578 }
3579
3580 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07003581 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08003582 false)) {
3583 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
3584 }
3585
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003586 owner.baseHardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07003587 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07003588 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Alan Viveretted70b9e72015-05-27 14:29:20 -07003589 if (owner.baseHardwareAccelerated) {
3590 ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
3591 }
Romain Guy812ccbe2010-06-01 14:07:24 -07003592
3593 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003594 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
3595 true)) {
3596 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
3597 }
3598
3599 if (sa.getBoolean(
3600 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
3601 false)) {
3602 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
3603 }
3604
3605 if (sa.getBoolean(
3606 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
3607 true)) {
3608 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
3609 }
3610
Svet Ganov354cd3c2015-12-17 11:35:04 -08003611 // The parent package controls installation, hence specify test only installs.
3612 if (owner.parentPackage == null) {
3613 if (sa.getBoolean(
3614 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
3615 false)) {
3616 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
3617 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003618 }
3619
Jason parksa3cdaa52011-01-13 14:15:43 -06003620 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003621 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06003622 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003623 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06003624 }
3625
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003626 if (sa.getBoolean(
Alex Klyubin01a959d2015-03-18 10:05:45 -07003627 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
3628 true)) {
3629 ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
3630 }
3631
3632 if (sa.getBoolean(
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003633 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
3634 false /* default is no RTL support*/)) {
3635 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
3636 }
3637
Narayan Kamath589a1bc2014-07-03 14:43:26 +01003638 if (sa.getBoolean(
3639 com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
3640 false)) {
3641 ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
3642 }
3643
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07003644 if (sa.getBoolean(
3645 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
3646 true)) {
3647 ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
3648 }
3649
Todd Kennedyd022ac22016-04-13 10:49:29 -07003650 if (sa.getBoolean(
3651 R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
3652 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003653 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003654 }
Todd Kennedyd022ac22016-04-13 10:49:29 -07003655 if (sa.getBoolean(
3656 R.styleable.AndroidManifestApplication_directBootAware,
3657 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003658 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003659 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003660
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003661 if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
3662 if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003663 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
3664 } else {
3665 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003666 }
3667 } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003668 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Wale Ogunwale6afdf912016-01-30 13:01:33 -08003669 }
3670
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07003671 ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
3672
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003673 ai.networkSecurityConfigRes = sa.getResourceId(
3674 com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig,
3675 0);
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07003676 ai.category = sa.getInt(
3677 com.android.internal.R.styleable.AndroidManifestApplication_appCategory,
3678 ApplicationInfo.CATEGORY_UNDEFINED);
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003679
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003680 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003681 str = sa.getNonConfigurationString(
3682 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003683 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
3684
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003685 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3686 str = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003687 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
3688 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003689 } else {
3690 // Some older apps have been seen to use a resource reference
3691 // here that on older builds was ignored (with a warning). We
3692 // need to continue to do this for them so they don't break.
3693 str = sa.getNonResourceString(
3694 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
3695 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003696 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
3697 str, outError);
3698
3699 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003700 CharSequence pname;
3701 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3702 pname = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003703 com.android.internal.R.styleable.AndroidManifestApplication_process,
3704 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003705 } else {
3706 // Some older apps have been seen to use a resource reference
3707 // here that on older builds was ignored (with a warning). We
3708 // need to continue to do this for them so they don't break.
3709 pname = sa.getNonResourceString(
3710 com.android.internal.R.styleable.AndroidManifestApplication_process);
3711 }
3712 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003713 flags, mSeparateProcesses, outError);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003714
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003715 ai.enabled = sa.getBoolean(
3716 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003717
Jose Lima12d0b4c2014-03-14 16:55:12 -07003718 if (sa.getBoolean(
3719 com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
3720 ai.flags |= ApplicationInfo.FLAG_IS_GAME;
3721 }
3722
Dianne Hackborn02486b12010-08-26 14:18:37 -07003723 if (false) {
3724 if (sa.getBoolean(
3725 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
3726 false)) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08003727 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07003728
3729 // A heavy-weight application can not be in a custom process.
3730 // We can do direct compare because we intern all strings.
3731 if (ai.processName != null && ai.processName != ai.packageName) {
3732 outError[0] = "cantSaveState applications can not use custom processes";
3733 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003734 }
3735 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003736 }
3737
Adam Powell269248d2011-08-02 10:26:54 -07003738 ai.uiOptions = sa.getInt(
3739 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
3740
Narayan Kamath96c11c52017-08-09 13:07:21 +01003741 ai.classLoaderName = sa.getString(
3742 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
3743 if (ai.classLoaderName != null
3744 && !ClassLoaderFactory.isValidClassLoaderName(ai.classLoaderName)) {
3745 outError[0] = "Invalid class loader name: " + ai.classLoaderName;
3746 }
3747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003748 sa.recycle();
3749
3750 if (outError[0] != null) {
3751 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3752 return false;
3753 }
3754
3755 final int innerDepth = parser.getDepth();
Garrett Boyer52136662017-05-23 13:47:58 -07003756 // IMPORTANT: These must only be cached for a single <application> to avoid components
3757 // getting added to the wrong package.
3758 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003759 int type;
Bryce Lee22571db2017-07-07 15:54:18 -07003760
Kenny Rootd2d29252011-08-08 11:27:57 -07003761 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3762 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3763 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003764 continue;
3765 }
3766
3767 String tagName = parser.getName();
3768 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003769 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003770 owner.baseHardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003771 if (a == null) {
3772 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3773 return false;
3774 }
3775
3776 owner.activities.add(a);
3777
3778 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003779 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
3780 true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003781 if (a == null) {
3782 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3783 return false;
3784 }
3785
3786 owner.receivers.add(a);
3787
3788 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003789 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003790 if (s == null) {
3791 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3792 return false;
3793 }
3794
3795 owner.services.add(s);
3796
3797 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003798 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003799 if (p == null) {
3800 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3801 return false;
3802 }
3803
3804 owner.providers.add(p);
3805
3806 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003807 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003808 if (a == null) {
3809 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3810 return false;
3811 }
3812
3813 owner.activities.add(a);
3814
3815 } else if (parser.getName().equals("meta-data")) {
3816 // note: application meta-data is stored off to the side, so it can
3817 // remain null in the primary copy (we like to avoid extra copies because
3818 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003819 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003820 outError)) == null) {
3821 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3822 return false;
3823 }
Svet Ganov67882122016-12-11 16:36:34 -08003824 } else if (tagName.equals("static-library")) {
3825 sa = res.obtainAttributes(parser,
3826 com.android.internal.R.styleable.AndroidManifestStaticLibrary);
3827
3828 // Note: don't allow this value to be a reference to a resource
3829 // that may change.
3830 final String lname = sa.getNonResourceString(
3831 com.android.internal.R.styleable.AndroidManifestStaticLibrary_name);
3832 final int version = sa.getInt(
3833 com.android.internal.R.styleable.AndroidManifestStaticLibrary_version, -1);
3834
3835 sa.recycle();
3836
3837 // Since the app canot run without a static lib - fail if malformed
3838 if (lname == null || version < 0) {
3839 outError[0] = "Bad static-library declaration name: " + lname
3840 + " version: " + version;
3841 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3842 XmlUtils.skipCurrentTag(parser);
3843 return false;
3844 }
3845
3846 if (owner.mSharedUserId != null) {
3847 outError[0] = "sharedUserId not allowed in static shared library";
3848 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
3849 XmlUtils.skipCurrentTag(parser);
3850 return false;
3851 }
3852
3853 if (owner.staticSharedLibName != null) {
3854 outError[0] = "Multiple static-shared libs for package " + pkgName;
3855 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3856 XmlUtils.skipCurrentTag(parser);
3857 return false;
3858 }
3859
3860 owner.staticSharedLibName = lname.intern();
3861 owner.staticSharedLibVersion = version;
3862 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY;
3863
3864 XmlUtils.skipCurrentTag(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003865
Dianne Hackbornc895be72013-03-11 17:48:43 -07003866 } else if (tagName.equals("library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003867 sa = res.obtainAttributes(parser,
Dianne Hackbornc895be72013-03-11 17:48:43 -07003868 com.android.internal.R.styleable.AndroidManifestLibrary);
3869
3870 // Note: don't allow this value to be a reference to a resource
3871 // that may change.
3872 String lname = sa.getNonResourceString(
3873 com.android.internal.R.styleable.AndroidManifestLibrary_name);
3874
3875 sa.recycle();
3876
3877 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003878 lname = lname.intern();
3879 if (!ArrayUtils.contains(owner.libraryNames, lname)) {
Svet Ganov67882122016-12-11 16:36:34 -08003880 owner.libraryNames = ArrayUtils.add(
3881 owner.libraryNames, lname);
Dianne Hackbornc895be72013-03-11 17:48:43 -07003882 }
3883 }
3884
3885 XmlUtils.skipCurrentTag(parser);
3886
Svet Ganov67882122016-12-11 16:36:34 -08003887 } else if (tagName.equals("uses-static-library")) {
3888 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
3889 return false;
3890 }
3891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003892 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003893 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003894 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3895
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003896 // Note: don't allow this value to be a reference to a resource
3897 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003898 String lname = sa.getNonResourceString(
3899 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07003900 boolean req = sa.getBoolean(
3901 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3902 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003903
3904 sa.recycle();
3905
Dianne Hackborn49237342009-08-27 20:08:01 -07003906 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003907 lname = lname.intern();
Dianne Hackborn49237342009-08-27 20:08:01 -07003908 if (req) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003909 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07003910 } else {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003911 owner.usesOptionalLibraries = ArrayUtils.add(
3912 owner.usesOptionalLibraries, lname);
3913 }
3914 }
3915
3916 XmlUtils.skipCurrentTag(parser);
3917
3918 } else if (tagName.equals("uses-package")) {
3919 // Dependencies for app installers; we don't currently try to
3920 // enforce this.
3921 XmlUtils.skipCurrentTag(parser);
3922
3923 } else {
3924 if (!RIGID_PARSER) {
3925 Slog.w(TAG, "Unknown element under <application>: " + tagName
3926 + " at " + mArchiveSourcePath + " "
3927 + parser.getPositionDescription());
3928 XmlUtils.skipCurrentTag(parser);
3929 continue;
3930 } else {
3931 outError[0] = "Bad element under <application>: " + tagName;
3932 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3933 return false;
3934 }
3935 }
3936 }
3937
Bryce Lee22571db2017-07-07 15:54:18 -07003938 // Must be ran after the entire {@link ApplicationInfo} has been fully processed and after
3939 // every activity info has had a chance to set it from its attributes.
3940 setMaxAspectRatio(owner);
3941
Paul Duffin855d7022017-07-10 15:16:07 +01003942 PackageBackwardCompatibility.modifySharedLibraries(owner);
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00003943
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003944 if (hasDomainURLs(owner)) {
3945 owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3946 } else {
3947 owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3948 }
3949
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003950 return true;
3951 }
3952
3953 /**
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003954 * 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 -07003955 */
3956 private static boolean hasDomainURLs(Package pkg) {
3957 if (pkg == null || pkg.activities == null) return false;
3958 final ArrayList<Activity> activities = pkg.activities;
3959 final int countActivities = activities.size();
3960 for (int n=0; n<countActivities; n++) {
3961 Activity activity = activities.get(n);
3962 ArrayList<ActivityIntentInfo> filters = activity.intents;
3963 if (filters == null) continue;
3964 final int countFilters = filters.size();
3965 for (int m=0; m<countFilters; m++) {
3966 ActivityIntentInfo aii = filters.get(m);
3967 if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003968 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003969 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
3970 aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
3971 return true;
3972 }
3973 }
3974 }
3975 return false;
3976 }
3977
3978 /**
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003979 * Parse the {@code application} XML tree at the current parse location in a
3980 * <em>split APK</em> manifest.
3981 * <p>
3982 * Note that split APKs have many more restrictions on what they're capable
3983 * of doing, so many valid features of a base APK have been carefully
3984 * omitted here.
3985 */
Svet Ganov354cd3c2015-12-17 11:35:04 -08003986 private boolean parseSplitApplication(Package owner, Resources res, XmlResourceParser parser,
3987 int flags, int splitIndex, String[] outError)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003988 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003989 TypedArray sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003990 com.android.internal.R.styleable.AndroidManifestApplication);
3991
3992 if (sa.getBoolean(
3993 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
3994 owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
3995 }
3996
Narayan Kamath96c11c52017-08-09 13:07:21 +01003997 final String classLoaderName = sa.getString(
3998 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
3999 if (classLoaderName == null || ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) {
4000 owner.applicationInfo.splitClassLoaderNames[splitIndex] = classLoaderName;
4001 } else {
4002 outError[0] = "Invalid class loader name: " + classLoaderName;
4003 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4004 return false;
4005 }
4006
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004007 final int innerDepth = parser.getDepth();
4008 int type;
4009 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
4010 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
4011 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4012 continue;
4013 }
4014
Adam Lesinski4e862812016-11-21 16:02:24 -08004015 ComponentInfo parsedComponent = null;
4016
Garrett Boyer52136662017-05-23 13:47:58 -07004017 // IMPORTANT: These must only be cached for a single <application> to avoid components
4018 // getting added to the wrong package.
4019 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004020 String tagName = parser.getName();
4021 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004022 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004023 owner.baseHardwareAccelerated);
4024 if (a == null) {
4025 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4026 return false;
4027 }
4028
4029 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08004030 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004031
4032 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004033 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
4034 true, false);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004035 if (a == null) {
4036 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4037 return false;
4038 }
4039
4040 owner.receivers.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08004041 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004042
4043 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004044 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004045 if (s == null) {
4046 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4047 return false;
4048 }
4049
4050 owner.services.add(s);
Adam Lesinski4e862812016-11-21 16:02:24 -08004051 parsedComponent = s.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004052
4053 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004054 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004055 if (p == null) {
4056 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4057 return false;
4058 }
4059
4060 owner.providers.add(p);
Adam Lesinski4e862812016-11-21 16:02:24 -08004061 parsedComponent = p.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004062
4063 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07004064 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004065 if (a == null) {
4066 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4067 return false;
4068 }
4069
4070 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08004071 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004072
4073 } else if (parser.getName().equals("meta-data")) {
4074 // note: application meta-data is stored off to the side, so it can
4075 // remain null in the primary copy (we like to avoid extra copies because
4076 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08004077 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004078 outError)) == null) {
4079 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4080 return false;
4081 }
4082
Svet Ganov67882122016-12-11 16:36:34 -08004083 } else if (tagName.equals("uses-static-library")) {
4084 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
4085 return false;
4086 }
4087
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004088 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004089 sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07004090 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
4091
4092 // Note: don't allow this value to be a reference to a resource
4093 // that may change.
4094 String lname = sa.getNonResourceString(
4095 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
4096 boolean req = sa.getBoolean(
4097 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
4098 true);
4099
4100 sa.recycle();
4101
4102 if (lname != null) {
4103 lname = lname.intern();
4104 if (req) {
4105 // Upgrade to treat as stronger constraint
4106 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
4107 owner.usesOptionalLibraries = ArrayUtils.remove(
4108 owner.usesOptionalLibraries, lname);
4109 } else {
4110 // Ignore if someone already defined as required
4111 if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
4112 owner.usesOptionalLibraries = ArrayUtils.add(
4113 owner.usesOptionalLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07004114 }
4115 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004116 }
4117
4118 XmlUtils.skipCurrentTag(parser);
4119
Dianne Hackborncef65ee2010-09-30 18:27:22 -07004120 } else if (tagName.equals("uses-package")) {
4121 // Dependencies for app installers; we don't currently try to
4122 // enforce this.
4123 XmlUtils.skipCurrentTag(parser);
4124
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004125 } else {
4126 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004127 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004128 + " at " + mArchiveSourcePath + " "
4129 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004130 XmlUtils.skipCurrentTag(parser);
4131 continue;
4132 } else {
4133 outError[0] = "Bad element under <application>: " + tagName;
4134 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4135 return false;
4136 }
4137 }
Adam Lesinski4e862812016-11-21 16:02:24 -08004138
4139 if (parsedComponent != null && parsedComponent.splitName == null) {
4140 // If the loaded component did not specify a split, inherit the split name
4141 // based on the split it is defined in.
4142 // This is used to later load the correct split when starting this
4143 // component.
4144 parsedComponent.splitName = owner.splitNames[splitIndex];
4145 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004146 }
4147
4148 return true;
4149 }
4150
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004151 private static boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
4152 String[] outError, String tag, TypedArray sa, boolean nameRequired,
4153 int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00004154 // This case can only happen in unit tests where we sometimes need to create fakes
4155 // of various package parser data structures.
4156 if (sa == null) {
4157 outError[0] = tag + " does not contain any attributes";
4158 return false;
4159 }
4160
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004161 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004162 if (name == null) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004163 if (nameRequired) {
4164 outError[0] = tag + " does not specify android:name";
4165 return false;
4166 }
4167 } else {
4168 outInfo.name
4169 = buildClassName(owner.applicationInfo.packageName, name, outError);
4170 if (outInfo.name == null) {
4171 return false;
4172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173 }
4174
Todd Kennedya83bfca2016-06-03 07:52:17 -07004175 final boolean useRoundIcon =
4176 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
4177 int roundIconVal = useRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004178 if (roundIconVal != 0) {
4179 outInfo.icon = roundIconVal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004180 outInfo.nonLocalizedLabel = null;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004181 } else {
4182 int iconVal = sa.getResourceId(iconRes, 0);
4183 if (iconVal != 0) {
4184 outInfo.icon = iconVal;
4185 outInfo.nonLocalizedLabel = null;
4186 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004187 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004188
Adam Powell81cd2e92010-04-21 16:35:18 -07004189 int logoVal = sa.getResourceId(logoRes, 0);
4190 if (logoVal != 0) {
4191 outInfo.logo = logoVal;
4192 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004193
Jose Limaf78e3122014-03-06 12:13:15 -08004194 int bannerVal = sa.getResourceId(bannerRes, 0);
4195 if (bannerVal != 0) {
4196 outInfo.banner = bannerVal;
4197 }
4198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004199 TypedValue v = sa.peekValue(labelRes);
4200 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4201 outInfo.nonLocalizedLabel = v.coerceToString();
4202 }
4203
4204 outInfo.packageName = owner.packageName;
4205
4206 return true;
4207 }
4208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004209 private Activity parseActivity(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004210 XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs,
Romain Guy529b60a2010-08-03 18:05:47 -07004211 boolean receiver, boolean hardwareAccelerated)
4212 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004213 TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004214
Garrett Boyer52136662017-05-23 13:47:58 -07004215 if (cachedArgs.mActivityArgs == null) {
4216 cachedArgs.mActivityArgs = new ParseComponentArgs(owner, outError,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004217 R.styleable.AndroidManifestActivity_name,
4218 R.styleable.AndroidManifestActivity_label,
4219 R.styleable.AndroidManifestActivity_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004220 R.styleable.AndroidManifestActivity_roundIcon,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004221 R.styleable.AndroidManifestActivity_logo,
4222 R.styleable.AndroidManifestActivity_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004223 mSeparateProcesses,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004224 R.styleable.AndroidManifestActivity_process,
4225 R.styleable.AndroidManifestActivity_description,
4226 R.styleable.AndroidManifestActivity_enabled);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004227 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004228
Garrett Boyer52136662017-05-23 13:47:58 -07004229 cachedArgs.mActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
4230 cachedArgs.mActivityArgs.sa = sa;
4231 cachedArgs.mActivityArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004232
Garrett Boyer52136662017-05-23 13:47:58 -07004233 Activity a = new Activity(cachedArgs.mActivityArgs, new ActivityInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004234 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004235 sa.recycle();
4236 return null;
4237 }
4238
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004239 boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004240 if (setExported) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004241 a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004242 }
4243
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004244 a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004245
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004246 a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
Adam Powell269248d2011-08-02 10:26:54 -07004247 a.info.applicationInfo.uiOptions);
4248
Adam Powelldd8fab22012-03-22 17:47:27 -07004249 String parentName = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004250 R.styleable.AndroidManifestActivity_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004251 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004252 if (parentName != null) {
4253 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4254 if (outError[0] == null) {
4255 a.info.parentActivityName = parentClassName;
4256 } else {
4257 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
4258 parentName);
4259 outError[0] = null;
4260 }
4261 }
4262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004263 String str;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004264 str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004265 if (str == null) {
4266 a.info.permission = owner.applicationInfo.permission;
4267 } else {
4268 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4269 }
4270
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004271 str = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004272 R.styleable.AndroidManifestActivity_taskAffinity,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004273 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004274 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
4275 owner.applicationInfo.taskAffinity, str, outError);
4276
Todd Kennedye9d0d272017-01-23 06:49:29 -08004277 a.info.splitName =
4278 sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_splitName, 0);
4279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004280 a.info.flags = 0;
4281 if (sa.getBoolean(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004282 R.styleable.AndroidManifestActivity_multiprocess, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004283 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
4284 }
4285
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004286 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004287 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
4288 }
4289
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004290 if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004291 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
4292 }
4293
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004294 if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004295 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
4296 }
4297
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004298 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004299 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
4300 }
4301
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004302 if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004303 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
4304 }
4305
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004306 if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004307 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
4308 }
4309
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004310 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004311 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
4312 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
4313 }
4314
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004315 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
Dianne Hackbornffa42482009-09-23 22:20:11 -07004316 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
4317 }
4318
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07004319 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
4320 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
4321 a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Craig Mautner5962b122012-10-05 14:45:52 -07004322 }
4323
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004324 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
Daniel Sandler613dde42010-06-21 13:46:39 -04004325 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
4326 }
Craig Mautner5962b122012-10-05 14:45:52 -07004327
Fyodor Kupolov4f5de342015-08-25 10:08:45 -07004328 if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
4329 a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
Fyodor Kupolov703d1c42015-01-27 11:59:00 -08004330 }
4331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004332 if (!receiver) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004333 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07004334 hardwareAccelerated)) {
4335 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
4336 }
4337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004338 a.info.launchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004339 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
Craig Mautner2dac0562014-05-06 09:06:44 -07004340 a.info.documentLaunchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004341 R.styleable.AndroidManifestActivity_documentLaunchMode,
Craig Mautner2dac0562014-05-06 09:06:44 -07004342 ActivityInfo.DOCUMENT_LAUNCH_NONE);
Craig Mautnerffcfcaa2014-06-05 09:54:38 -07004343 a.info.maxRecents = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004344 R.styleable.AndroidManifestActivity_maxRecents,
Dianne Hackborn852975d2014-08-22 17:42:43 -07004345 ActivityManager.getDefaultAppRecentsLimitStatic());
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004346 a.info.configChanges = getActivityConfigChanges(
4347 sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004348 sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004349 a.info.softInputMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004350 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
Craig Mautner2dac0562014-05-06 09:06:44 -07004351
Craig Mautner43e52ed2014-06-16 17:18:52 -07004352 a.info.persistableMode = sa.getInteger(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004353 R.styleable.AndroidManifestActivity_persistableMode,
Craig Mautner43e52ed2014-06-16 17:18:52 -07004354 ActivityInfo.PERSIST_ROOT_ONLY);
Craig Mautner2dac0562014-05-06 09:06:44 -07004355
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004356 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004357 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
4358 }
4359
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004360 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004361 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
4362 }
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004363
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004364 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004365 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
4366 }
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004367
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004368 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004369 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
4370 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004371
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004372 a.info.screenOrientation = sa.getInt(
4373 R.styleable.AndroidManifestActivity_screenOrientation,
4374 SCREEN_ORIENTATION_UNSPECIFIED);
Wale Ogunwale6a591362015-10-05 20:18:27 -07004375
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004376 setActivityResizeMode(a.info, sa, owner);
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004377
Winson Chungd3395382016-12-13 11:49:09 -08004378 if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
4379 false)) {
4380 a.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE;
4381 }
4382
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004383 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004384 a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004385 }
Wale Ogunwaleb60692e2015-10-24 12:35:56 -07004386
Bryce Lee22571db2017-07-07 15:54:18 -07004387 if (sa.hasValue(R.styleable.AndroidManifestActivity_maxAspectRatio)
4388 && sa.getType(R.styleable.AndroidManifestActivity_maxAspectRatio)
4389 == TypedValue.TYPE_FLOAT) {
4390 a.setMaxAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_maxAspectRatio,
4391 0 /*default*/));
4392 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004393
Craig Mautner15df08a2015-04-01 12:17:18 -07004394 a.info.lockTaskLaunchMode =
4395 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004396
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004397 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4398 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004399 false);
Ruben Brunkf56c9f42016-04-22 18:20:55 -07004400
4401 a.info.requestedVrComponent =
4402 sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
Robert Carr0f5d7532016-10-17 16:39:17 -07004403
4404 a.info.rotationAnimation =
Robert Carr427ba4f2017-07-17 18:37:06 -07004405 sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, ROTATION_ANIMATION_UNSPECIFIED);
Romain Guy48327452017-01-23 17:03:35 -08004406
4407 a.info.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode,
4408 ActivityInfo.COLOR_MODE_DEFAULT);
chaviw59b98852017-06-13 12:05:44 -07004409
4410 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showWhenLocked, false)) {
4411 a.info.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
4412 }
4413
4414 if (sa.getBoolean(R.styleable.AndroidManifestActivity_turnScreenOn, false)) {
4415 a.info.flags |= ActivityInfo.FLAG_TURN_SCREEN_ON;
4416 }
4417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004418 } else {
4419 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
4420 a.info.configChanges = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004421
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004422 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07004423 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07004424 if (a.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004425 Slog.w(TAG, "Activity exported request ignored due to singleUser: "
4426 + a.className + " at " + mArchiveSourcePath + " "
4427 + parser.getPositionDescription());
4428 a.info.exported = false;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07004429 setExported = true;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004430 }
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004431 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004432
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004433 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4434 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004435 false);
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004436 }
4437
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004438 if (a.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004439 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004440 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004441 }
4442
Todd Kennedy752fb702017-03-21 16:28:10 -07004443 // can't make this final; we may set it later via meta-data
4444 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08004445 sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004446 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004447 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004448 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004449 }
4450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004451 sa.recycle();
4452
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004453 if (receiver && (owner.applicationInfo.privateFlags
4454 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004455 // A heavy-weight application can not have receives in its main process
4456 // We can do direct compare because we intern all strings.
4457 if (a.info.processName == owner.packageName) {
4458 outError[0] = "Heavy-weight applications can not have receivers in main process";
4459 }
4460 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004462 if (outError[0] != null) {
4463 return null;
4464 }
4465
4466 int outerDepth = parser.getDepth();
4467 int type;
4468 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4469 && (type != XmlPullParser.END_TAG
4470 || parser.getDepth() > outerDepth)) {
4471 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4472 continue;
4473 }
4474
4475 if (parser.getName().equals("intent-filter")) {
4476 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004477 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4478 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004479 return null;
4480 }
4481 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004482 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004483 + mArchiveSourcePath + " "
4484 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004485 } else {
4486 a.intents.add(intent);
4487 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004488 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004489 final int visibility = visibleToEphemeral
4490 ? IntentFilter.VISIBILITY_EXPLICIT
4491 : !receiver && isImplicitlyExposedIntent(intent)
4492 ? IntentFilter.VISIBILITY_IMPLICIT
4493 : IntentFilter.VISIBILITY_NONE;
4494 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004495 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004496 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4497 }
4498 if (intent.isImplicitlyVisibleToInstantApp()) {
4499 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004500 }
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -07004501 if (LOG_UNSAFE_BROADCASTS && receiver
4502 && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
4503 for (int i = 0; i < intent.countActions(); i++) {
4504 final String action = intent.getAction(i);
4505 if (action == null || !action.startsWith("android.")) continue;
4506 if (!SAFE_BROADCASTS.contains(action)) {
4507 Slog.w(TAG, "Broadcast " + action + " may never be delivered to "
4508 + owner.packageName + " as requested at: "
4509 + parser.getPositionDescription());
4510 }
4511 }
4512 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004513 } else if (!receiver && parser.getName().equals("preferred")) {
4514 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004515 if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/,
4516 intent, outError)) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004517 return null;
4518 }
4519 if (intent.countActions() == 0) {
4520 Slog.w(TAG, "No actions in preferred at "
4521 + mArchiveSourcePath + " "
4522 + parser.getPositionDescription());
4523 } else {
4524 if (owner.preferredActivityFilters == null) {
4525 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
4526 }
4527 owner.preferredActivityFilters.add(intent);
4528 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004529 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004530 final int visibility = visibleToEphemeral
4531 ? IntentFilter.VISIBILITY_EXPLICIT
4532 : !receiver && isImplicitlyExposedIntent(intent)
4533 ? IntentFilter.VISIBILITY_IMPLICIT
4534 : IntentFilter.VISIBILITY_NONE;
4535 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004536 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004537 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4538 }
4539 if (intent.isImplicitlyVisibleToInstantApp()) {
4540 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004542 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004543 if ((a.metaData = parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004544 outError)) == null) {
4545 return null;
4546 }
Todd Kennedy752fb702017-03-21 16:28:10 -07004547 // we don't have an attribute [or it's false], but, we have meta-data
4548 if (!visibleToEphemeral && a.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
4549 visibleToEphemeral = true; // set in case there are more intent filters
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004550 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4551 a.info.flags &= ~ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy752fb702017-03-21 16:28:10 -07004552 owner.visibleToInstantApps = true;
4553 // cycle through any filters already seen
4554 for (int i = a.intents.size() - 1; i >= 0; --i) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004555 a.intents.get(i)
4556 .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
Todd Kennedy752fb702017-03-21 16:28:10 -07004557 }
4558 if (owner.preferredActivityFilters != null) {
4559 for (int i = owner.preferredActivityFilters.size() - 1; i >= 0; --i) {
4560 owner.preferredActivityFilters.get(i)
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004561 .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
Todd Kennedy752fb702017-03-21 16:28:10 -07004562 }
4563 }
4564 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004565 } else if (!receiver && parser.getName().equals("layout")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004566 parseLayout(res, parser, a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004567 } else {
4568 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004569 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004570 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004571 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004572 + " at " + mArchiveSourcePath + " "
4573 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004574 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004575 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004576 + " at " + mArchiveSourcePath + " "
4577 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004578 }
4579 XmlUtils.skipCurrentTag(parser);
4580 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004582 if (receiver) {
4583 outError[0] = "Bad element under <receiver>: " + parser.getName();
4584 } else {
4585 outError[0] = "Bad element under <activity>: " + parser.getName();
4586 }
4587 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004588 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004589 }
4590 }
4591
4592 if (!setExported) {
4593 a.info.exported = a.intents.size() > 0;
4594 }
4595
4596 return a;
4597 }
4598
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004599 private void setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package owner) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004600 final boolean appExplicitDefault = (owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004601 & (PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE
4602 | PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE)) != 0;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004603
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004604 if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity)
4605 || appExplicitDefault) {
4606 // Activity or app explicitly set if it is resizeable or not;
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004607 final boolean appResizeable = (owner.applicationInfo.privateFlags
4608 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE) != 0;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004609 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity,
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004610 appResizeable)) {
Winson Chungd3395382016-12-13 11:49:09 -08004611 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004612 } else {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004613 aInfo.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004614 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004615 return;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004616 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004617
4618 if ((owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004619 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) != 0) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004620 // The activity or app didn't explicitly set the resizing option, however we want to
4621 // make it resize due to the sdk version it is targeting.
4622 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
4623 return;
4624 }
4625
4626 // resize preference isn't set and target sdk version doesn't support resizing apps by
4627 // default. For the app to be resizeable if it isn't fixed orientation or immersive.
skuhne@google.com322347b2016-12-02 12:54:03 -08004628 if (aInfo.isFixedOrientationPortrait()) {
4629 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
4630 } else if (aInfo.isFixedOrientationLandscape()) {
4631 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
4632 } else if (aInfo.isFixedOrientation()) {
4633 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
4634 } else {
4635 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
4636 }
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004637 }
4638
Bryce Lee22571db2017-07-07 15:54:18 -07004639 /**
4640 * Sets every the max aspect ratio of every child activity that doesn't already have an aspect
4641 * ratio set.
4642 */
4643 private void setMaxAspectRatio(Package owner) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004644 // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater.
4645 // NOTE: 16.7:9 was the max aspect ratio Android devices can support pre-O per the CDD.
Bryce Lee22571db2017-07-07 15:54:18 -07004646 float maxAspectRatio = owner.applicationInfo.targetSdkVersion < O
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004647 ? DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0;
Bryce Lee22571db2017-07-07 15:54:18 -07004648
4649 if (owner.applicationInfo.maxAspectRatio != 0) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004650 // Use the application max aspect ration as default if set.
Bryce Lee22571db2017-07-07 15:54:18 -07004651 maxAspectRatio = owner.applicationInfo.maxAspectRatio;
4652 } else if (owner.mAppMetaData != null
4653 && owner.mAppMetaData.containsKey(METADATA_MAX_ASPECT_RATIO)) {
4654 maxAspectRatio = owner.mAppMetaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004655 }
4656
Bryce Lee22571db2017-07-07 15:54:18 -07004657 for (Activity activity : owner.activities) {
4658 // If the max aspect ratio for the activity has already been set, skip.
4659 if (activity.hasMaxAspectRatio()) {
4660 continue;
4661 }
4662
4663 // By default we prefer to use a values defined on the activity directly than values
4664 // defined on the application. We do not check the styled attributes on the activity
4665 // as it would have already been set when we processed the activity. We wait to process
4666 // the meta data here since this method is called at the end of processing the
4667 // application and all meta data is guaranteed.
4668 final float activityAspectRatio = activity.metaData != null
4669 ? activity.metaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio)
4670 : maxAspectRatio;
4671
4672 activity.setMaxAspectRatio(activityAspectRatio);
Wale Ogunwale0cb70ac2017-03-27 09:16:38 -07004673 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004674 }
4675
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004676 /**
4677 * @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml.
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004678 * @param recreateOnConfigChanges The bit mask recreateOnConfigChanges fetched from
4679 * AndroidManifest.xml.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004680 * @hide Exposed for unit testing only.
4681 */
4682 @TestApi
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004683 public static int getActivityConfigChanges(int configChanges, int recreateOnConfigChanges) {
4684 return configChanges | ((~recreateOnConfigChanges) & RECREATE_ON_CONFIG_CHANGES_MASK);
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004685 }
4686
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004687 private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004688 TypedArray sw = res.obtainAttributes(attrs,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004689 com.android.internal.R.styleable.AndroidManifestLayout);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004690 int width = -1;
4691 float widthFraction = -1f;
4692 int height = -1;
4693 float heightFraction = -1f;
4694 final int widthType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004695 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004696 if (widthType == TypedValue.TYPE_FRACTION) {
4697 widthFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004698 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004699 1, 1, -1);
4700 } else if (widthType == TypedValue.TYPE_DIMENSION) {
4701 width = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004702 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004703 -1);
4704 }
4705 final int heightType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004706 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004707 if (heightType == TypedValue.TYPE_FRACTION) {
4708 heightFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004709 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004710 1, 1, -1);
4711 } else if (heightType == TypedValue.TYPE_DIMENSION) {
4712 height = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004713 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004714 -1);
4715 }
4716 int gravity = sw.getInt(
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004717 com.android.internal.R.styleable.AndroidManifestLayout_gravity,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004718 Gravity.CENTER);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004719 int minWidth = sw.getDimensionPixelSize(
4720 com.android.internal.R.styleable.AndroidManifestLayout_minWidth,
Andrii Kulian2e751b82016-03-16 16:59:32 -07004721 -1);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004722 int minHeight = sw.getDimensionPixelSize(
4723 com.android.internal.R.styleable.AndroidManifestLayout_minHeight,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004724 -1);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004725 sw.recycle();
Andrii Kulian2e751b82016-03-16 16:59:32 -07004726 a.info.windowLayout = new ActivityInfo.WindowLayout(width, widthFraction,
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004727 height, heightFraction, gravity, minWidth, minHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004728 }
4729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004730 private Activity parseActivityAlias(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004731 XmlResourceParser parser, int flags, String[] outError,
4732 CachedComponentArgs cachedArgs)
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004733 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004734 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004735 com.android.internal.R.styleable.AndroidManifestActivityAlias);
4736
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004737 String targetActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004738 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
4739 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004740 if (targetActivity == null) {
4741 outError[0] = "<activity-alias> does not specify android:targetActivity";
4742 sa.recycle();
4743 return null;
4744 }
4745
4746 targetActivity = buildClassName(owner.applicationInfo.packageName,
4747 targetActivity, outError);
4748 if (targetActivity == null) {
4749 sa.recycle();
4750 return null;
4751 }
4752
Garrett Boyer52136662017-05-23 13:47:58 -07004753 if (cachedArgs.mActivityAliasArgs == null) {
4754 cachedArgs.mActivityAliasArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004755 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
4756 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
4757 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004758 com.android.internal.R.styleable.AndroidManifestActivityAlias_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004759 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004760 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004761 mSeparateProcesses,
4762 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004763 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004764 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07004765 cachedArgs.mActivityAliasArgs.tag = "<activity-alias>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004766 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004767
Garrett Boyer52136662017-05-23 13:47:58 -07004768 cachedArgs.mActivityAliasArgs.sa = sa;
4769 cachedArgs.mActivityAliasArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004770
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004771 Activity target = null;
4772
4773 final int NA = owner.activities.size();
4774 for (int i=0; i<NA; i++) {
4775 Activity t = owner.activities.get(i);
4776 if (targetActivity.equals(t.info.name)) {
4777 target = t;
4778 break;
4779 }
4780 }
4781
4782 if (target == null) {
4783 outError[0] = "<activity-alias> target activity " + targetActivity
4784 + " not found in manifest";
4785 sa.recycle();
4786 return null;
4787 }
4788
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004789 ActivityInfo info = new ActivityInfo();
4790 info.targetActivity = targetActivity;
4791 info.configChanges = target.info.configChanges;
4792 info.flags = target.info.flags;
4793 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07004794 info.logo = target.info.logo;
Jose Limaf78e3122014-03-06 12:13:15 -08004795 info.banner = target.info.banner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004796 info.labelRes = target.info.labelRes;
4797 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
4798 info.launchMode = target.info.launchMode;
Yao Chen597ad3f2015-06-09 16:00:14 -07004799 info.lockTaskLaunchMode = target.info.lockTaskLaunchMode;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004800 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004801 if (info.descriptionRes == 0) {
4802 info.descriptionRes = target.info.descriptionRes;
4803 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004804 info.screenOrientation = target.info.screenOrientation;
4805 info.taskAffinity = target.info.taskAffinity;
4806 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07004807 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07004808 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07004809 info.parentActivityName = target.info.parentActivityName;
Craig Mautner8307ea72014-09-11 15:03:53 -07004810 info.maxRecents = target.info.maxRecents;
Andrii Kulian2e751b82016-03-16 16:59:32 -07004811 info.windowLayout = target.info.windowLayout;
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004812 info.resizeMode = target.info.resizeMode;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004813 info.maxAspectRatio = target.info.maxAspectRatio;
Bryce Lee22571db2017-07-07 15:54:18 -07004814
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004815 info.encryptionAware = info.directBootAware = target.info.directBootAware;
Craig Mautner8307ea72014-09-11 15:03:53 -07004816
Garrett Boyer52136662017-05-23 13:47:58 -07004817 Activity a = new Activity(cachedArgs.mActivityAliasArgs, info);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004818 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004819 sa.recycle();
4820 return null;
4821 }
4822
4823 final boolean setExported = sa.hasValue(
4824 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
4825 if (setExported) {
4826 a.info.exported = sa.getBoolean(
4827 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
4828 }
4829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004830 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004831 str = sa.getNonConfigurationString(
4832 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004833 if (str != null) {
4834 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4835 }
4836
Adam Powelldd8fab22012-03-22 17:47:27 -07004837 String parentName = sa.getNonConfigurationString(
4838 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004839 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004840 if (parentName != null) {
4841 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4842 if (outError[0] == null) {
4843 a.info.parentActivityName = parentClassName;
4844 } else {
4845 Log.e(TAG, "Activity alias " + a.info.name +
4846 " specified invalid parentActivityName " + parentName);
4847 outError[0] = null;
4848 }
4849 }
4850
Chad Brubaker699c7712017-01-20 13:53:42 -08004851 // TODO add visibleToInstantApps attribute to activity alias
Todd Kennedybe0b8892017-02-15 14:13:52 -08004852 final boolean visibleToEphemeral =
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004853 ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004855 sa.recycle();
4856
4857 if (outError[0] != null) {
4858 return null;
4859 }
4860
4861 int outerDepth = parser.getDepth();
4862 int type;
4863 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4864 && (type != XmlPullParser.END_TAG
4865 || parser.getDepth() > outerDepth)) {
4866 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4867 continue;
4868 }
4869
4870 if (parser.getName().equals("intent-filter")) {
4871 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004872 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4873 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004874 return null;
4875 }
4876 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004877 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004878 + mArchiveSourcePath + " "
4879 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004880 } else {
4881 a.intents.add(intent);
4882 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004883 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004884 final int visibility = visibleToEphemeral
4885 ? IntentFilter.VISIBILITY_EXPLICIT
4886 : isImplicitlyExposedIntent(intent)
4887 ? IntentFilter.VISIBILITY_IMPLICIT
4888 : IntentFilter.VISIBILITY_NONE;
4889 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004890 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004891 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4892 }
4893 if (intent.isImplicitlyVisibleToInstantApp()) {
4894 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004895 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004896 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004897 if ((a.metaData=parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004898 outError)) == null) {
4899 return null;
4900 }
4901 } else {
4902 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004903 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004904 + " at " + mArchiveSourcePath + " "
4905 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004906 XmlUtils.skipCurrentTag(parser);
4907 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004908 } else {
4909 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
4910 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004912 }
4913 }
4914
4915 if (!setExported) {
4916 a.info.exported = a.intents.size() > 0;
4917 }
4918
4919 return a;
4920 }
4921
4922 private Provider parseProvider(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004923 XmlResourceParser parser, int flags, String[] outError,
4924 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004925 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004926 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004927 com.android.internal.R.styleable.AndroidManifestProvider);
4928
Garrett Boyer52136662017-05-23 13:47:58 -07004929 if (cachedArgs.mProviderArgs == null) {
4930 cachedArgs.mProviderArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004931 com.android.internal.R.styleable.AndroidManifestProvider_name,
4932 com.android.internal.R.styleable.AndroidManifestProvider_label,
4933 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004934 com.android.internal.R.styleable.AndroidManifestProvider_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004935 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004936 com.android.internal.R.styleable.AndroidManifestProvider_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004937 mSeparateProcesses,
4938 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004939 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004940 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07004941 cachedArgs.mProviderArgs.tag = "<provider>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004942 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004943
Garrett Boyer52136662017-05-23 13:47:58 -07004944 cachedArgs.mProviderArgs.sa = sa;
4945 cachedArgs.mProviderArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004946
Garrett Boyer52136662017-05-23 13:47:58 -07004947 Provider p = new Provider(cachedArgs.mProviderArgs, new ProviderInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004948 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004949 sa.recycle();
4950 return null;
4951 }
4952
Nick Kralevichf097b162012-07-28 12:43:48 -07004953 boolean providerExportedDefault = false;
4954
4955 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
4956 // For compatibility, applications targeting API level 16 or lower
4957 // should have their content providers exported by default, unless they
4958 // specify otherwise.
4959 providerExportedDefault = true;
4960 }
4961
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004962 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07004963 com.android.internal.R.styleable.AndroidManifestProvider_exported,
4964 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004965
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004966 String cpname = sa.getNonConfigurationString(
4967 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004968
4969 p.info.isSyncable = sa.getBoolean(
4970 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
4971 false);
4972
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004973 String permission = sa.getNonConfigurationString(
4974 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
4975 String str = sa.getNonConfigurationString(
4976 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977 if (str == null) {
4978 str = permission;
4979 }
4980 if (str == null) {
4981 p.info.readPermission = owner.applicationInfo.permission;
4982 } else {
4983 p.info.readPermission =
4984 str.length() > 0 ? str.toString().intern() : null;
4985 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004986 str = sa.getNonConfigurationString(
4987 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004988 if (str == null) {
4989 str = permission;
4990 }
4991 if (str == null) {
4992 p.info.writePermission = owner.applicationInfo.permission;
4993 } else {
4994 p.info.writePermission =
4995 str.length() > 0 ? str.toString().intern() : null;
4996 }
4997
4998 p.info.grantUriPermissions = sa.getBoolean(
4999 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
5000 false);
5001
5002 p.info.multiprocess = sa.getBoolean(
5003 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
5004 false);
5005
5006 p.info.initOrder = sa.getInt(
5007 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
5008 0);
5009
Todd Kennedye9d0d272017-01-23 06:49:29 -08005010 p.info.splitName =
5011 sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_splitName, 0);
5012
Dianne Hackborn7d19e022012-08-07 19:12:33 -07005013 p.info.flags = 0;
5014
5015 if (sa.getBoolean(
5016 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
5017 false)) {
5018 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07005019 if (p.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -07005020 Slog.w(TAG, "Provider exported request ignored due to singleUser: "
5021 + p.className + " at " + mArchiveSourcePath + " "
5022 + parser.getPositionDescription());
5023 p.info.exported = false;
5024 }
5025 }
5026
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005027 p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
5028 R.styleable.AndroidManifestProvider_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07005029 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005030 if (p.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07005031 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005032 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07005033 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08005034
Todd Kennedybe0b8892017-02-15 14:13:52 -08005035 final boolean visibleToEphemeral =
5036 sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005037 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005038 p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005039 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005040 }
5041
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005042 sa.recycle();
5043
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005044 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
5045 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005046 // A heavy-weight application can not have providers in its main process
5047 // We can do direct compare because we intern all strings.
5048 if (p.info.processName == owner.packageName) {
5049 outError[0] = "Heavy-weight applications can not have providers in main process";
5050 return null;
5051 }
5052 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005054 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07005055 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005056 return null;
5057 }
Dianne Hackborn1bc177c2014-12-03 10:20:30 -08005058 if (cpname.length() <= 0) {
5059 outError[0] = "<provider> has empty authorities attribute";
5060 return null;
5061 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005062 p.info.authority = cpname.intern();
5063
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005064 if (!parseProviderTags(
Todd Kennedy752fb702017-03-21 16:28:10 -07005065 res, parser, visibleToEphemeral, owner, p, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005066 return null;
5067 }
5068
5069 return p;
5070 }
5071
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005072 private boolean parseProviderTags(Resources res, XmlResourceParser parser,
Todd Kennedy752fb702017-03-21 16:28:10 -07005073 boolean visibleToEphemeral, Package owner, Provider outInfo, String[] outError)
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005074 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005075 int outerDepth = parser.getDepth();
5076 int type;
5077 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5078 && (type != XmlPullParser.END_TAG
5079 || parser.getDepth() > outerDepth)) {
5080 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5081 continue;
5082 }
5083
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005084 if (parser.getName().equals("intent-filter")) {
5085 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005086 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
5087 intent, outError)) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005088 return false;
5089 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005090 if (visibleToEphemeral) {
5091 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
5092 outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005093 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005094 outInfo.intents.add(intent);
Jeff Sharkey85f5f812013-10-07 10:16:12 -07005095
5096 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005097 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005098 outInfo.metaData, outError)) == null) {
5099 return false;
5100 }
Todd Kennedy752fb702017-03-21 16:28:10 -07005101 // we don't have an attribute [or it's false], but, we have meta-data
5102 if (!visibleToEphemeral && outInfo.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
5103 visibleToEphemeral = true; // set in case there are more intent filters
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005104 outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy752fb702017-03-21 16:28:10 -07005105 owner.visibleToInstantApps = true;
5106 // cycle through any filters already seen
5107 for (int i = outInfo.intents.size() - 1; i >= 0; --i) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005108 outInfo.intents.get(i)
5109 .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
Todd Kennedy752fb702017-03-21 16:28:10 -07005110 }
5111 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005113 } else if (parser.getName().equals("grant-uri-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005114 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005115 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
5116
5117 PatternMatcher pa = null;
5118
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005119 String str = sa.getNonConfigurationString(
5120 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005121 if (str != null) {
5122 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
5123 }
5124
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005125 str = sa.getNonConfigurationString(
5126 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005127 if (str != null) {
5128 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
5129 }
5130
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005131 str = sa.getNonConfigurationString(
5132 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005133 if (str != null) {
5134 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5135 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005137 sa.recycle();
5138
5139 if (pa != null) {
5140 if (outInfo.info.uriPermissionPatterns == null) {
5141 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
5142 outInfo.info.uriPermissionPatterns[0] = pa;
5143 } else {
5144 final int N = outInfo.info.uriPermissionPatterns.length;
5145 PatternMatcher[] newp = new PatternMatcher[N+1];
5146 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
5147 newp[N] = pa;
5148 outInfo.info.uriPermissionPatterns = newp;
5149 }
5150 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005151 } else {
5152 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005153 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005154 + parser.getName() + " at " + mArchiveSourcePath + " "
5155 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005156 XmlUtils.skipCurrentTag(parser);
5157 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005158 } else {
5159 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5160 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005161 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005162 }
5163 XmlUtils.skipCurrentTag(parser);
5164
5165 } else if (parser.getName().equals("path-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005166 TypedArray sa = res.obtainAttributes(parser,
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005167 com.android.internal.R.styleable.AndroidManifestPathPermission);
5168
5169 PathPermission pa = null;
5170
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005171 String permission = sa.getNonConfigurationString(
5172 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
5173 String readPermission = sa.getNonConfigurationString(
5174 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005175 if (readPermission == null) {
5176 readPermission = permission;
5177 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005178 String writePermission = sa.getNonConfigurationString(
5179 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005180 if (writePermission == null) {
5181 writePermission = permission;
5182 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005183
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005184 boolean havePerm = false;
5185 if (readPermission != null) {
5186 readPermission = readPermission.intern();
5187 havePerm = true;
5188 }
5189 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00005190 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005191 havePerm = true;
5192 }
5193
5194 if (!havePerm) {
5195 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005196 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005197 + parser.getName() + " at " + mArchiveSourcePath + " "
5198 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005199 XmlUtils.skipCurrentTag(parser);
5200 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005201 } else {
5202 outError[0] = "No readPermission or writePermssion for <path-permission>";
5203 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005204 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005205 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005206
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005207 String path = sa.getNonConfigurationString(
5208 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005209 if (path != null) {
5210 pa = new PathPermission(path,
5211 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
5212 }
5213
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005214 path = sa.getNonConfigurationString(
5215 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005216 if (path != null) {
5217 pa = new PathPermission(path,
5218 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
5219 }
5220
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005221 path = sa.getNonConfigurationString(
5222 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005223 if (path != null) {
5224 pa = new PathPermission(path,
5225 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
5226 }
5227
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005228 path = sa.getNonConfigurationString(
5229 com.android.internal.R.styleable.AndroidManifestPathPermission_pathAdvancedPattern, 0);
5230 if (path != null) {
5231 pa = new PathPermission(path,
5232 PatternMatcher.PATTERN_ADVANCED_GLOB, readPermission, writePermission);
5233 }
5234
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005235 sa.recycle();
5236
5237 if (pa != null) {
5238 if (outInfo.info.pathPermissions == null) {
5239 outInfo.info.pathPermissions = new PathPermission[1];
5240 outInfo.info.pathPermissions[0] = pa;
5241 } else {
5242 final int N = outInfo.info.pathPermissions.length;
5243 PathPermission[] newp = new PathPermission[N+1];
5244 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
5245 newp[N] = pa;
5246 outInfo.info.pathPermissions = newp;
5247 }
5248 } else {
5249 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005250 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005251 + parser.getName() + " at " + mArchiveSourcePath + " "
5252 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005253 XmlUtils.skipCurrentTag(parser);
5254 continue;
5255 }
5256 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5257 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005258 }
5259 XmlUtils.skipCurrentTag(parser);
5260
5261 } else {
5262 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005263 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005264 + parser.getName() + " at " + mArchiveSourcePath + " "
5265 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005266 XmlUtils.skipCurrentTag(parser);
5267 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005268 } else {
5269 outError[0] = "Bad element under <provider>: " + parser.getName();
5270 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005271 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005272 }
5273 }
5274 return true;
5275 }
5276
5277 private Service parseService(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07005278 XmlResourceParser parser, int flags, String[] outError,
5279 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005280 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005281 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005282 com.android.internal.R.styleable.AndroidManifestService);
5283
Garrett Boyer52136662017-05-23 13:47:58 -07005284 if (cachedArgs.mServiceArgs == null) {
5285 cachedArgs.mServiceArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005286 com.android.internal.R.styleable.AndroidManifestService_name,
5287 com.android.internal.R.styleable.AndroidManifestService_label,
5288 com.android.internal.R.styleable.AndroidManifestService_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005289 com.android.internal.R.styleable.AndroidManifestService_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07005290 com.android.internal.R.styleable.AndroidManifestService_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08005291 com.android.internal.R.styleable.AndroidManifestService_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005292 mSeparateProcesses,
5293 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005294 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005295 com.android.internal.R.styleable.AndroidManifestService_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07005296 cachedArgs.mServiceArgs.tag = "<service>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005297 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005298
Garrett Boyer52136662017-05-23 13:47:58 -07005299 cachedArgs.mServiceArgs.sa = sa;
5300 cachedArgs.mServiceArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005301
Garrett Boyer52136662017-05-23 13:47:58 -07005302 Service s = new Service(cachedArgs.mServiceArgs, new ServiceInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005303 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005304 sa.recycle();
5305 return null;
5306 }
5307
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005308 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005309 com.android.internal.R.styleable.AndroidManifestService_exported);
5310 if (setExported) {
5311 s.info.exported = sa.getBoolean(
5312 com.android.internal.R.styleable.AndroidManifestService_exported, false);
5313 }
5314
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005315 String str = sa.getNonConfigurationString(
5316 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005317 if (str == null) {
5318 s.info.permission = owner.applicationInfo.permission;
5319 } else {
5320 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
5321 }
5322
Todd Kennedye9d0d272017-01-23 06:49:29 -08005323 s.info.splitName =
5324 sa.getNonConfigurationString(R.styleable.AndroidManifestService_splitName, 0);
5325
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005326 s.info.flags = 0;
5327 if (sa.getBoolean(
5328 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
5329 false)) {
5330 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
5331 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08005332 if (sa.getBoolean(
5333 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
5334 false)) {
5335 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
5336 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005337 if (sa.getBoolean(
Robert Sesekb9a86662015-12-09 16:22:45 -05005338 com.android.internal.R.styleable.AndroidManifestService_externalService,
5339 false)) {
5340 s.info.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE;
5341 }
5342 if (sa.getBoolean(
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005343 com.android.internal.R.styleable.AndroidManifestService_singleUser,
5344 false)) {
5345 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07005346 if (s.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005347 Slog.w(TAG, "Service exported request ignored due to singleUser: "
5348 + s.className + " at " + mArchiveSourcePath + " "
5349 + parser.getPositionDescription());
5350 s.info.exported = false;
Amith Yamasani4b9d79c2014-05-21 19:14:21 -07005351 setExported = true;
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005352 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005353 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005354
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005355 s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
5356 R.styleable.AndroidManifestService_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07005357 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005358 if (s.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07005359 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005360 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07005361 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08005362
Todd Kennedy752fb702017-03-21 16:28:10 -07005363 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08005364 sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005365 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005366 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005367 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005368 }
5369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005370 sa.recycle();
5371
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005372 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
5373 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005374 // A heavy-weight application can not have services in its main process
5375 // We can do direct compare because we intern all strings.
5376 if (s.info.processName == owner.packageName) {
5377 outError[0] = "Heavy-weight applications can not have services in main process";
5378 return null;
5379 }
5380 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005382 int outerDepth = parser.getDepth();
5383 int type;
5384 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5385 && (type != XmlPullParser.END_TAG
5386 || parser.getDepth() > outerDepth)) {
5387 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5388 continue;
5389 }
5390
5391 if (parser.getName().equals("intent-filter")) {
5392 ServiceIntentInfo intent = new ServiceIntentInfo(s);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005393 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
5394 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005395 return null;
5396 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005397 if (visibleToEphemeral) {
5398 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
5399 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005401 s.intents.add(intent);
5402 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005403 if ((s.metaData=parseMetaData(res, parser, s.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005404 outError)) == null) {
5405 return null;
5406 }
Todd Kennedy752fb702017-03-21 16:28:10 -07005407 // we don't have an attribute [or it's false], but, we have meta-data
5408 if (!visibleToEphemeral && s.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
5409 visibleToEphemeral = true; // set in case there are more intent filters
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005410 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy752fb702017-03-21 16:28:10 -07005411 owner.visibleToInstantApps = true;
5412 // cycle through any filters already seen
5413 for (int i = s.intents.size() - 1; i >= 0; --i) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005414 s.intents.get(i)
5415 .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
Todd Kennedy752fb702017-03-21 16:28:10 -07005416 }
5417 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005418 } else {
5419 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005420 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005421 + parser.getName() + " at " + mArchiveSourcePath + " "
5422 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005423 XmlUtils.skipCurrentTag(parser);
5424 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005425 } else {
5426 outError[0] = "Bad element under <service>: " + parser.getName();
5427 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005429 }
5430 }
5431
5432 if (!setExported) {
5433 s.info.exported = s.intents.size() > 0;
5434 }
5435
5436 return s;
5437 }
5438
Chad Brubaker49414832017-04-13 16:13:23 -07005439 private boolean isImplicitlyExposedIntent(IntentInfo intent) {
5440 return intent.hasCategory(Intent.CATEGORY_BROWSABLE)
5441 || intent.hasAction(Intent.ACTION_SEND)
5442 || intent.hasAction(Intent.ACTION_SENDTO)
5443 || intent.hasAction(Intent.ACTION_SEND_MULTIPLE);
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005444 }
5445
Svet Ganov354cd3c2015-12-17 11:35:04 -08005446 private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag,
5447 Component<?> outInfo, String[] outError) throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005448 int outerDepth = parser.getDepth();
5449 int type;
5450 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5451 && (type != XmlPullParser.END_TAG
5452 || parser.getDepth() > outerDepth)) {
5453 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5454 continue;
5455 }
5456
5457 if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005458 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005459 outInfo.metaData, outError)) == null) {
5460 return false;
5461 }
5462 } else {
5463 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005464 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005465 + parser.getName() + " at " + mArchiveSourcePath + " "
5466 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005467 XmlUtils.skipCurrentTag(parser);
5468 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005469 } else {
5470 outError[0] = "Bad element under " + tag + ": " + parser.getName();
5471 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005473 }
5474 }
5475 return true;
5476 }
5477
5478 private Bundle parseMetaData(Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08005479 XmlResourceParser parser, Bundle data, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005480 throws XmlPullParserException, IOException {
5481
Svet Ganov354cd3c2015-12-17 11:35:04 -08005482 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005483 com.android.internal.R.styleable.AndroidManifestMetaData);
5484
5485 if (data == null) {
5486 data = new Bundle();
5487 }
5488
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005489 String name = sa.getNonConfigurationString(
5490 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005491 if (name == null) {
5492 outError[0] = "<meta-data> requires an android:name attribute";
5493 sa.recycle();
5494 return null;
5495 }
5496
Dianne Hackborn854060af2009-07-09 18:14:31 -07005497 name = name.intern();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005498
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005499 TypedValue v = sa.peekValue(
5500 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
5501 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005502 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005503 data.putInt(name, v.resourceId);
5504 } else {
5505 v = sa.peekValue(
5506 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07005507 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005508 if (v != null) {
5509 if (v.type == TypedValue.TYPE_STRING) {
5510 CharSequence cs = v.coerceToString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00005511 data.putString(name, cs != null ? cs.toString() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005512 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
5513 data.putBoolean(name, v.data != 0);
5514 } else if (v.type >= TypedValue.TYPE_FIRST_INT
5515 && v.type <= TypedValue.TYPE_LAST_INT) {
5516 data.putInt(name, v.data);
5517 } else if (v.type == TypedValue.TYPE_FLOAT) {
5518 data.putFloat(name, v.getFloat());
5519 } else {
5520 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005521 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005522 + parser.getName() + " at " + mArchiveSourcePath + " "
5523 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005524 } else {
5525 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
5526 data = null;
5527 }
5528 }
5529 } else {
5530 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
5531 data = null;
5532 }
5533 }
5534
5535 sa.recycle();
5536
5537 XmlUtils.skipCurrentTag(parser);
5538
5539 return data;
5540 }
5541
Adam Lesinski4e862812016-11-21 16:02:24 -08005542 private static VerifierInfo parseVerifier(AttributeSet attrs) {
5543 String packageName = null;
5544 String encodedPublicKey = null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005545
Adam Lesinski4e862812016-11-21 16:02:24 -08005546 final int attrCount = attrs.getAttributeCount();
5547 for (int i = 0; i < attrCount; i++) {
5548 final int attrResId = attrs.getAttributeNameResource(i);
5549 switch (attrResId) {
5550 case com.android.internal.R.attr.name:
5551 packageName = attrs.getAttributeValue(i);
5552 break;
Kenny Root05ca4c92011-09-15 10:36:25 -07005553
Adam Lesinski4e862812016-11-21 16:02:24 -08005554 case com.android.internal.R.attr.publicKey:
5555 encodedPublicKey = attrs.getAttributeValue(i);
5556 break;
5557 }
5558 }
Kenny Root05ca4c92011-09-15 10:36:25 -07005559
5560 if (packageName == null || packageName.length() == 0) {
5561 Slog.i(TAG, "verifier package name was null; skipping");
5562 return null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005563 }
5564
Christopher Tate30147332014-04-15 12:57:47 -07005565 final PublicKey publicKey = parsePublicKey(encodedPublicKey);
5566 if (publicKey == null) {
5567 Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
5568 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -08005569 }
5570
Christopher Tate30147332014-04-15 12:57:47 -07005571 return new VerifierInfo(packageName, publicKey);
Geremy Condraf1bcca82013-01-07 22:35:24 -08005572 }
5573
Christopher Tate30147332014-04-15 12:57:47 -07005574 public static final PublicKey parsePublicKey(final String encodedPublicKey) {
5575 if (encodedPublicKey == null) {
dcashman1616f302015-05-29 14:47:23 -07005576 Slog.w(TAG, "Could not parse null public key");
Christopher Tate30147332014-04-15 12:57:47 -07005577 return null;
5578 }
5579
Kenny Root05ca4c92011-09-15 10:36:25 -07005580 EncodedKeySpec keySpec;
5581 try {
5582 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
5583 keySpec = new X509EncodedKeySpec(encoded);
5584 } catch (IllegalArgumentException e) {
dcashman1616f302015-05-29 14:47:23 -07005585 Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07005586 return null;
5587 }
5588
5589 /* First try the key as an RSA key. */
5590 try {
5591 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005592 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005593 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005594 Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005595 } catch (InvalidKeySpecException e) {
5596 // Not a RSA public key.
5597 }
5598
dcashman1616f302015-05-29 14:47:23 -07005599 /* Now try it as a ECDSA key. */
5600 try {
5601 final KeyFactory keyFactory = KeyFactory.getInstance("EC");
5602 return keyFactory.generatePublic(keySpec);
5603 } catch (NoSuchAlgorithmException e) {
5604 Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build");
5605 } catch (InvalidKeySpecException e) {
5606 // Not a ECDSA public key.
5607 }
5608
Kenny Root05ca4c92011-09-15 10:36:25 -07005609 /* Now try it as a DSA key. */
5610 try {
5611 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005612 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005613 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005614 Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005615 } catch (InvalidKeySpecException e) {
5616 // Not a DSA public key.
5617 }
5618
dcashman1616f302015-05-29 14:47:23 -07005619 /* Not a supported key type */
Kenny Root05ca4c92011-09-15 10:36:25 -07005620 return null;
5621 }
5622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005623 private static final String ANDROID_RESOURCES
5624 = "http://schemas.android.com/apk/res/android";
5625
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005626 private boolean parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs,
5627 boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
5628 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005629
Svet Ganov354cd3c2015-12-17 11:35:04 -08005630 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005631 com.android.internal.R.styleable.AndroidManifestIntentFilter);
5632
5633 int priority = sa.getInt(
5634 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005635 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08005636
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005637 TypedValue v = sa.peekValue(
5638 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
5639 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
5640 outInfo.nonLocalizedLabel = v.coerceToString();
5641 }
5642
Todd Kennedya83bfca2016-06-03 07:52:17 -07005643 final boolean useRoundIcon =
5644 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
5645 int roundIconVal = useRoundIcon ? sa.getResourceId(
5646 com.android.internal.R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0;
5647 if (roundIconVal != 0) {
5648 outInfo.icon = roundIconVal;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005649 } else {
5650 outInfo.icon = sa.getResourceId(
5651 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
5652 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005653
Adam Powell81cd2e92010-04-21 16:35:18 -07005654 outInfo.logo = sa.getResourceId(
5655 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005656
Jose Limaf78e3122014-03-06 12:13:15 -08005657 outInfo.banner = sa.getResourceId(
5658 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
5659
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08005660 if (allowAutoVerify) {
5661 outInfo.setAutoVerify(sa.getBoolean(
5662 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
5663 false));
5664 }
5665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005666 sa.recycle();
5667
5668 int outerDepth = parser.getDepth();
5669 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07005670 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
5671 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
5672 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005673 continue;
5674 }
5675
5676 String nodeName = parser.getName();
5677 if (nodeName.equals("action")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005678 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005679 ANDROID_RESOURCES, "name");
5680 if (value == null || value == "") {
5681 outError[0] = "No value supplied for <android:name>";
5682 return false;
5683 }
5684 XmlUtils.skipCurrentTag(parser);
5685
5686 outInfo.addAction(value);
5687 } else if (nodeName.equals("category")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005688 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005689 ANDROID_RESOURCES, "name");
5690 if (value == null || value == "") {
5691 outError[0] = "No value supplied for <android:name>";
5692 return false;
5693 }
5694 XmlUtils.skipCurrentTag(parser);
5695
5696 outInfo.addCategory(value);
5697
5698 } else if (nodeName.equals("data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005699 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005700 com.android.internal.R.styleable.AndroidManifestData);
5701
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005702 String str = sa.getNonConfigurationString(
5703 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005704 if (str != null) {
5705 try {
5706 outInfo.addDataType(str);
5707 } catch (IntentFilter.MalformedMimeTypeException e) {
5708 outError[0] = e.toString();
5709 sa.recycle();
5710 return false;
5711 }
5712 }
5713
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005714 str = sa.getNonConfigurationString(
5715 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005716 if (str != null) {
5717 outInfo.addDataScheme(str);
5718 }
5719
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005720 str = sa.getNonConfigurationString(
5721 com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
5722 if (str != null) {
5723 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
5724 }
5725
5726 str = sa.getNonConfigurationString(
5727 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
5728 if (str != null) {
5729 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
5730 }
5731
5732 str = sa.getNonConfigurationString(
5733 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
5734 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005735 if (!allowGlobs) {
5736 outError[0] = "sspPattern not allowed here; ssp must be literal";
5737 return false;
5738 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005739 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5740 }
5741
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005742 String host = sa.getNonConfigurationString(
5743 com.android.internal.R.styleable.AndroidManifestData_host, 0);
5744 String port = sa.getNonConfigurationString(
5745 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005746 if (host != null) {
5747 outInfo.addDataAuthority(host, port);
5748 }
5749
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005750 str = sa.getNonConfigurationString(
5751 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005752 if (str != null) {
5753 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
5754 }
5755
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005756 str = sa.getNonConfigurationString(
5757 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005758 if (str != null) {
5759 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
5760 }
5761
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005762 str = sa.getNonConfigurationString(
5763 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005764 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005765 if (!allowGlobs) {
5766 outError[0] = "pathPattern not allowed here; path must be literal";
5767 return false;
5768 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005769 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5770 }
5771
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005772 str = sa.getNonConfigurationString(
5773 com.android.internal.R.styleable.AndroidManifestData_pathAdvancedPattern, 0);
5774 if (str != null) {
5775 if (!allowGlobs) {
5776 outError[0] = "pathAdvancedPattern not allowed here; path must be literal";
5777 return false;
5778 }
5779 outInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB);
5780 }
5781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005782 sa.recycle();
5783 XmlUtils.skipCurrentTag(parser);
5784 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005785 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005786 + parser.getName() + " at " + mArchiveSourcePath + " "
5787 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005788 XmlUtils.skipCurrentTag(parser);
5789 } else {
5790 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
5791 return false;
5792 }
5793 }
5794
5795 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07005796
5797 if (DEBUG_PARSER) {
5798 final StringBuilder cats = new StringBuilder("Intent d=");
5799 cats.append(outInfo.hasDefault);
5800 cats.append(", cat=");
5801
5802 final Iterator<String> it = outInfo.categoriesIterator();
5803 if (it != null) {
5804 while (it.hasNext()) {
5805 cats.append(' ');
5806 cats.append(it.next());
5807 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005808 }
Kenny Rootd2d29252011-08-08 11:27:57 -07005809 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005810 }
5811
5812 return true;
5813 }
5814
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005815 /**
5816 * Representation of a full package parsed from APK files on disk. A package
5817 * consists of a single base APK, and zero or more split APKs.
5818 */
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00005819 public final static class Package implements Parcelable {
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07005820
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005821 public String packageName;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08005822
Svet Ganov67882122016-12-11 16:36:34 -08005823 // The package name declared in the manifest as the package can be
5824 // renamed, for example static shared libs use synthetic package names.
5825 public String manifestPackageName;
5826
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005827 /** Names of any split APKs, ordered by parsed splitName */
5828 public String[] splitNames;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005829
5830 // TODO: work towards making these paths invariant
Jeff Sharkey275e0852014-06-17 18:18:49 -07005831
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07005832 public String volumeUuid;
5833
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005834 /**
5835 * Path where this package was found on disk. For monolithic packages
5836 * this is path to single base APK file; for cluster packages this is
5837 * path to the cluster directory.
5838 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005839 public String codePath;
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005840
5841 /** Path of base APK */
5842 public String baseCodePath;
5843 /** Paths of any split APKs, ordered by parsed splitName */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005844 public String[] splitCodePaths;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005845
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08005846 /** Revision code of base APK */
5847 public int baseRevisionCode;
5848 /** Revision codes of any split APKs, ordered by parsed splitName */
5849 public int[] splitRevisionCodes;
5850
Jeff Sharkeyda96e132014-07-15 14:54:09 -07005851 /** Flags of any split APKs; ordered by parsed splitName */
5852 public int[] splitFlags;
5853
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005854 /**
5855 * Private flags of any split APKs; ordered by parsed splitName.
5856 *
5857 * {@hide}
5858 */
5859 public int[] splitPrivateFlags;
5860
Jeff Sharkeyda96e132014-07-15 14:54:09 -07005861 public boolean baseHardwareAccelerated;
5862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005863 // For now we only support one application per package.
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00005864 public ApplicationInfo applicationInfo = new ApplicationInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005865
5866 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
5867 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
5868 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
5869 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
5870 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
5871 public final ArrayList<Service> services = new ArrayList<Service>(0);
5872 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
5873
5874 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
5875
Dianne Hackborn854060af2009-07-09 18:14:31 -07005876 public ArrayList<String> protectedBroadcasts;
Dianne Hackbornc895be72013-03-11 17:48:43 -07005877
Svet Ganov354cd3c2015-12-17 11:35:04 -08005878 public Package parentPackage;
5879 public ArrayList<Package> childPackages;
5880
Svet Ganov67882122016-12-11 16:36:34 -08005881 public String staticSharedLibName = null;
5882 public int staticSharedLibVersion = 0;
Dianne Hackbornc895be72013-03-11 17:48:43 -07005883 public ArrayList<String> libraryNames = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07005884 public ArrayList<String> usesLibraries = null;
Svet Ganov67882122016-12-11 16:36:34 -08005885 public ArrayList<String> usesStaticLibraries = null;
5886 public int[] usesStaticLibrariesVersions = null;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07005887 public String[][] usesStaticLibrariesCertDigests = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07005888 public ArrayList<String> usesOptionalLibraries = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005889 public String[] usesLibraryFiles = null;
5890
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005891 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
5892
Dianne Hackbornc1552392010-03-03 16:19:01 -08005893 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005894 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08005895 public ArrayList<String> mAdoptPermissions = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005897 // We store the application meta-data independently to avoid multiple unwanted references
5898 public Bundle mAppMetaData = null;
5899
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005900 // The version code declared for this package.
5901 public int mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08005902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005903 // The version name declared for this package.
5904 public String mVersionName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005906 // The shared user id that this package wants to use.
5907 public String mSharedUserId;
5908
5909 // The shared user label that this package wants to use.
5910 public int mSharedUserLabel;
5911
5912 // Signatures that were read from the package.
Jeff Sharkey275e0852014-06-17 18:18:49 -07005913 public Signature[] mSignatures;
5914 public Certificate[][] mCertificates;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005915
5916 // For use by package manager service for quick lookup of
5917 // preferred up order.
5918 public int mPreferredOrder = 0;
5919
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07005920 // For use by package manager to keep track of when a package was last used.
Brian Carlstromca82e612016-04-19 23:16:08 -07005921 public long[] mLastPackageUsageTimeInMills =
5922 new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07005923
Amith Yamasani13593602012-03-22 16:16:17 -07005924 // // User set enabled state.
5925 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
5926 //
5927 // // Whether the package has been stopped.
5928 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08005929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005930 // Additional data supplied by callers.
5931 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07005932
Jeff Sharkeyda96e132014-07-15 14:54:09 -07005933 // Applications hardware preferences
5934 public ArrayList<ConfigurationInfo> configPreferences = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005935
Jeff Sharkeyda96e132014-07-15 14:54:09 -07005936 // Applications requested features
Dianne Hackborn49237342009-08-27 20:08:01 -07005937 public ArrayList<FeatureInfo> reqFeatures = null;
5938
Adam Lesinskid3edfde2014-08-08 17:32:44 -07005939 // Applications requested feature groups
5940 public ArrayList<FeatureGroupInfo> featureGroups = null;
5941
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08005942 public int installLocation;
5943
Jeff Hao272bf3a2014-10-08 13:34:43 -07005944 public boolean coreApp;
5945
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08005946 /* An app that's required for all users and cannot be uninstalled for a user */
5947 public boolean mRequiredForAllUsers;
5948
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07005949 /* The restricted account authenticator type that is used by this application */
5950 public String mRestrictedAccountType;
5951
Amith Yamasaniccbe3892013-04-12 17:52:42 -07005952 /* The required account type without which this application will not function */
5953 public String mRequiredAccountType;
5954
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01005955 public String mOverlayTarget;
Jaekyun Seok42d53f62017-04-10 13:48:58 +09005956 public int mOverlayPriority;
Jaekyun Seok04342892017-03-02 15:24:19 +09005957 public boolean mIsStaticOverlay;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01005958 public boolean mTrustedOverlay;
5959
Geremy Condraf1bcca82013-01-07 22:35:24 -08005960 /**
dcashman989eb3712014-06-17 12:56:12 -07005961 * Data used to feed the KeySetManagerService
Geremy Condraf1bcca82013-01-07 22:35:24 -08005962 */
dcashman989eb3712014-06-17 12:56:12 -07005963 public ArraySet<PublicKey> mSigningKeys;
5964 public ArraySet<String> mUpgradeKeySets;
5965 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -08005966
Narayan Kamath4903f642014-08-11 13:33:45 +01005967 /**
5968 * The install time abi override for this package, if any.
5969 *
5970 * TODO: This seems like a horrible place to put the abiOverride because
5971 * this isn't something the packageParser parsers. However, this fits in with
5972 * the rest of the PackageManager where package scanning randomly pushes
5973 * and prods fields out of {@code this.applicationInfo}.
5974 */
5975 public String cpuAbiOverride;
Selim Gurun2d291d82016-02-05 17:50:53 -08005976 /**
5977 * The install time abi override to choose 32bit abi's when multiple abi's
5978 * are present. This is only meaningfull for multiarch applications.
5979 * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
5980 */
5981 public boolean use32bitAbi;
Narayan Kamath4903f642014-08-11 13:33:45 +01005982
Todd Kennedyfdd241a2016-04-28 12:26:53 -07005983 public byte[] restrictUpdateHash;
5984
Todd Kennedy7c8addf2017-06-27 14:13:55 -07005985 /** Set if the app or any of its components are visible to instant applications. */
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005986 public boolean visibleToInstantApps;
Todd Kennedy7c8addf2017-06-27 14:13:55 -07005987 /** Whether or not the package is a stub and must be replaced by the full version. */
5988 public boolean isStub;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005989
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005990 public Package(String packageName) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005991 this.packageName = packageName;
Svet Ganov67882122016-12-11 16:36:34 -08005992 this.manifestPackageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07005993 applicationInfo.packageName = packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005994 applicationInfo.uid = -1;
5995 }
5996
Svet Ganov354cd3c2015-12-17 11:35:04 -08005997 public void setApplicationVolumeUuid(String volumeUuid) {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06005998 final UUID storageUuid = StorageManager.convert(volumeUuid);
Svet Ganov354cd3c2015-12-17 11:35:04 -08005999 this.applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006000 this.applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006001 if (childPackages != null) {
6002 final int packageCount = childPackages.size();
6003 for (int i = 0; i < packageCount; i++) {
6004 childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006005 childPackages.get(i).applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006006 }
6007 }
6008 }
6009
6010 public void setApplicationInfoCodePath(String codePath) {
6011 this.applicationInfo.setCodePath(codePath);
6012 if (childPackages != null) {
6013 final int packageCount = childPackages.size();
6014 for (int i = 0; i < packageCount; i++) {
6015 childPackages.get(i).applicationInfo.setCodePath(codePath);
6016 }
6017 }
6018 }
6019
6020 public void setApplicationInfoResourcePath(String resourcePath) {
6021 this.applicationInfo.setResourcePath(resourcePath);
6022 if (childPackages != null) {
6023 final int packageCount = childPackages.size();
6024 for (int i = 0; i < packageCount; i++) {
6025 childPackages.get(i).applicationInfo.setResourcePath(resourcePath);
6026 }
6027 }
6028 }
6029
6030 public void setApplicationInfoBaseResourcePath(String resourcePath) {
6031 this.applicationInfo.setBaseResourcePath(resourcePath);
6032 if (childPackages != null) {
6033 final int packageCount = childPackages.size();
6034 for (int i = 0; i < packageCount; i++) {
6035 childPackages.get(i).applicationInfo.setBaseResourcePath(resourcePath);
6036 }
6037 }
6038 }
6039
6040 public void setApplicationInfoBaseCodePath(String baseCodePath) {
6041 this.applicationInfo.setBaseCodePath(baseCodePath);
6042 if (childPackages != null) {
6043 final int packageCount = childPackages.size();
6044 for (int i = 0; i < packageCount; i++) {
6045 childPackages.get(i).applicationInfo.setBaseCodePath(baseCodePath);
6046 }
6047 }
6048 }
6049
Todd Kennedy13715d52016-08-01 13:38:57 -07006050 public List<String> getChildPackageNames() {
6051 if (childPackages == null) {
6052 return null;
6053 }
6054 final int childCount = childPackages.size();
6055 final List<String> childPackageNames = new ArrayList<>(childCount);
6056 for (int i = 0; i < childCount; i++) {
6057 String childPackageName = childPackages.get(i).packageName;
6058 childPackageNames.add(childPackageName);
6059 }
6060 return childPackageNames;
6061 }
6062
Svet Ganov354cd3c2015-12-17 11:35:04 -08006063 public boolean hasChildPackage(String packageName) {
6064 final int childCount = (childPackages != null) ? childPackages.size() : 0;
6065 for (int i = 0; i < childCount; i++) {
6066 if (childPackages.get(i).packageName.equals(packageName)) {
6067 return true;
6068 }
6069 }
6070 return false;
6071 }
6072
6073 public void setApplicationInfoSplitCodePaths(String[] splitCodePaths) {
6074 this.applicationInfo.setSplitCodePaths(splitCodePaths);
6075 // Children have no splits
6076 }
6077
6078 public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) {
6079 this.applicationInfo.setSplitResourcePaths(resroucePaths);
6080 // Children have no splits
6081 }
6082
6083 public void setSplitCodePaths(String[] codePaths) {
6084 this.splitCodePaths = codePaths;
6085 }
6086
6087 public void setCodePath(String codePath) {
6088 this.codePath = codePath;
6089 if (childPackages != null) {
6090 final int packageCount = childPackages.size();
6091 for (int i = 0; i < packageCount; i++) {
6092 childPackages.get(i).codePath = codePath;
6093 }
6094 }
6095 }
6096
6097 public void setBaseCodePath(String baseCodePath) {
6098 this.baseCodePath = baseCodePath;
6099 if (childPackages != null) {
6100 final int packageCount = childPackages.size();
6101 for (int i = 0; i < packageCount; i++) {
6102 childPackages.get(i).baseCodePath = baseCodePath;
6103 }
6104 }
6105 }
6106
6107 public void setSignatures(Signature[] signatures) {
6108 this.mSignatures = signatures;
6109 if (childPackages != null) {
6110 final int packageCount = childPackages.size();
6111 for (int i = 0; i < packageCount; i++) {
6112 childPackages.get(i).mSignatures = signatures;
6113 }
6114 }
6115 }
6116
6117 public void setVolumeUuid(String volumeUuid) {
6118 this.volumeUuid = volumeUuid;
6119 if (childPackages != null) {
6120 final int packageCount = childPackages.size();
6121 for (int i = 0; i < packageCount; i++) {
6122 childPackages.get(i).volumeUuid = volumeUuid;
6123 }
6124 }
6125 }
6126
6127 public void setApplicationInfoFlags(int mask, int flags) {
6128 applicationInfo.flags = (applicationInfo.flags & ~mask) | (mask & flags);
6129 if (childPackages != null) {
6130 final int packageCount = childPackages.size();
6131 for (int i = 0; i < packageCount; i++) {
6132 childPackages.get(i).applicationInfo.flags =
6133 (applicationInfo.flags & ~mask) | (mask & flags);
6134 }
6135 }
6136 }
6137
Selim Gurun75827b22016-02-09 10:55:33 -08006138 public void setUse32bitAbi(boolean use32bitAbi) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006139 this.use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006140 if (childPackages != null) {
6141 final int packageCount = childPackages.size();
6142 for (int i = 0; i < packageCount; i++) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006143 childPackages.get(i).use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006144 }
6145 }
6146 }
6147
Svetoslav Ganov40610e32017-06-20 19:35:51 -07006148 public boolean isLibrary() {
6149 return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames);
6150 }
6151
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006152 public List<String> getAllCodePaths() {
Jeff Sharkey275e0852014-06-17 18:18:49 -07006153 ArrayList<String> paths = new ArrayList<>();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006154 paths.add(baseCodePath);
Jeff Sharkey275e0852014-06-17 18:18:49 -07006155 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6156 Collections.addAll(paths, splitCodePaths);
6157 }
6158 return paths;
6159 }
6160
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006161 /**
6162 * Filtered set of {@link #getAllCodePaths()} that excludes
6163 * resource-only APKs.
6164 */
6165 public List<String> getAllCodePathsExcludingResourceOnly() {
6166 ArrayList<String> paths = new ArrayList<>();
6167 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6168 paths.add(baseCodePath);
6169 }
6170 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6171 for (int i = 0; i < splitCodePaths.length; i++) {
6172 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6173 paths.add(splitCodePaths[i]);
6174 }
6175 }
6176 }
6177 return paths;
6178 }
6179
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006180 public void setPackageName(String newName) {
6181 packageName = newName;
6182 applicationInfo.packageName = newName;
6183 for (int i=permissions.size()-1; i>=0; i--) {
6184 permissions.get(i).setPackageName(newName);
6185 }
6186 for (int i=permissionGroups.size()-1; i>=0; i--) {
6187 permissionGroups.get(i).setPackageName(newName);
6188 }
6189 for (int i=activities.size()-1; i>=0; i--) {
6190 activities.get(i).setPackageName(newName);
6191 }
6192 for (int i=receivers.size()-1; i>=0; i--) {
6193 receivers.get(i).setPackageName(newName);
6194 }
6195 for (int i=providers.size()-1; i>=0; i--) {
6196 providers.get(i).setPackageName(newName);
6197 }
6198 for (int i=services.size()-1; i>=0; i--) {
6199 services.get(i).setPackageName(newName);
6200 }
6201 for (int i=instrumentation.size()-1; i>=0; i--) {
6202 instrumentation.get(i).setPackageName(newName);
6203 }
6204 }
Dianne Hackborn65696252012-03-05 18:49:21 -08006205
6206 public boolean hasComponentClassName(String name) {
6207 for (int i=activities.size()-1; i>=0; i--) {
6208 if (name.equals(activities.get(i).className)) {
6209 return true;
6210 }
6211 }
6212 for (int i=receivers.size()-1; i>=0; i--) {
6213 if (name.equals(receivers.get(i).className)) {
6214 return true;
6215 }
6216 }
6217 for (int i=providers.size()-1; i>=0; i--) {
6218 if (name.equals(providers.get(i).className)) {
6219 return true;
6220 }
6221 }
6222 for (int i=services.size()-1; i>=0; i--) {
6223 if (name.equals(services.get(i).className)) {
6224 return true;
6225 }
6226 }
6227 for (int i=instrumentation.size()-1; i>=0; i--) {
6228 if (name.equals(instrumentation.get(i).className)) {
6229 return true;
6230 }
6231 }
6232 return false;
6233 }
6234
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08006235 /**
6236 * @hide
6237 */
6238 public boolean isForwardLocked() {
6239 return applicationInfo.isForwardLocked();
6240 }
6241
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006242 /**
6243 * @hide
6244 */
6245 public boolean isSystemApp() {
6246 return applicationInfo.isSystemApp();
6247 }
6248
6249 /**
6250 * @hide
6251 */
Svet Ganovadc1cf42015-06-15 16:36:24 -07006252 public boolean isPrivilegedApp() {
6253 return applicationInfo.isPrivilegedApp();
6254 }
6255
6256 /**
6257 * @hide
6258 */
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006259 public boolean isUpdatedSystemApp() {
6260 return applicationInfo.isUpdatedSystemApp();
6261 }
6262
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006263 /**
6264 * @hide
6265 */
6266 public boolean canHaveOatDir() {
6267 // The following app types CANNOT have oat directory
6268 // - non-updated system apps
6269 // - forward-locked apps or apps installed in ASEC containers
6270 return (!isSystemApp() || isUpdatedSystemApp())
6271 && !isForwardLocked() && !applicationInfo.isExternalAsec();
6272 }
6273
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006274 public boolean isMatch(int flags) {
6275 if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
6276 return isSystemApp();
6277 }
6278 return true;
6279 }
6280
Brian Carlstromca82e612016-04-19 23:16:08 -07006281 public long getLatestPackageUseTimeInMills() {
6282 long latestUse = 0L;
6283 for (long use : mLastPackageUsageTimeInMills) {
6284 latestUse = Math.max(latestUse, use);
6285 }
6286 return latestUse;
6287 }
6288
David Brazdil90e26992016-04-18 14:08:52 +01006289 public long getLatestForegroundPackageUseTimeInMills() {
6290 int[] foregroundReasons = {
6291 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
6292 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
6293 };
6294
6295 long latestUse = 0L;
6296 for (int reason : foregroundReasons) {
6297 latestUse = Math.max(latestUse, mLastPackageUsageTimeInMills[reason]);
6298 }
6299 return latestUse;
6300 }
6301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006302 public String toString() {
6303 return "Package{"
6304 + Integer.toHexString(System.identityHashCode(this))
6305 + " " + packageName + "}";
6306 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006307
6308 @Override
6309 public int describeContents() {
6310 return 0;
6311 }
6312
6313 public Package(Parcel dest) {
6314 // We use the boot classloader for all classes that we load.
6315 final ClassLoader boot = Object.class.getClassLoader();
6316
Narayan Kamath07ac1442017-02-10 15:08:07 +00006317 packageName = dest.readString().intern();
Svet Ganov67882122016-12-11 16:36:34 -08006318 manifestPackageName = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006319 splitNames = dest.readStringArray();
6320 volumeUuid = dest.readString();
6321 codePath = dest.readString();
6322 baseCodePath = dest.readString();
6323 splitCodePaths = dest.readStringArray();
6324 baseRevisionCode = dest.readInt();
6325 splitRevisionCodes = dest.createIntArray();
6326 splitFlags = dest.createIntArray();
6327 splitPrivateFlags = dest.createIntArray();
6328 baseHardwareAccelerated = (dest.readInt() == 1);
6329 applicationInfo = dest.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006330 if (applicationInfo.permission != null) {
6331 applicationInfo.permission = applicationInfo.permission.intern();
6332 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006333
6334 // We don't serialize the "owner" package and the application info object for each of
6335 // these components, in order to save space and to avoid circular dependencies while
6336 // serialization. We need to fix them all up here.
6337 dest.readParcelableList(permissions, boot);
6338 fixupOwner(permissions);
6339 dest.readParcelableList(permissionGroups, boot);
6340 fixupOwner(permissionGroups);
6341 dest.readParcelableList(activities, boot);
6342 fixupOwner(activities);
6343 dest.readParcelableList(receivers, boot);
6344 fixupOwner(receivers);
6345 dest.readParcelableList(providers, boot);
6346 fixupOwner(providers);
6347 dest.readParcelableList(services, boot);
6348 fixupOwner(services);
6349 dest.readParcelableList(instrumentation, boot);
6350 fixupOwner(instrumentation);
6351
6352 dest.readStringList(requestedPermissions);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006353 internStringArrayList(requestedPermissions);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006354 protectedBroadcasts = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006355 internStringArrayList(protectedBroadcasts);
6356
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006357 parentPackage = dest.readParcelable(boot);
6358
6359 childPackages = new ArrayList<>();
6360 dest.readParcelableList(childPackages, boot);
6361 if (childPackages.size() == 0) {
6362 childPackages = null;
6363 }
6364
Svet Ganov67882122016-12-11 16:36:34 -08006365 staticSharedLibName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006366 if (staticSharedLibName != null) {
6367 staticSharedLibName = staticSharedLibName.intern();
6368 }
Svet Ganov67882122016-12-11 16:36:34 -08006369 staticSharedLibVersion = dest.readInt();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006370 libraryNames = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006371 internStringArrayList(libraryNames);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006372 usesLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006373 internStringArrayList(usesLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006374 usesOptionalLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006375 internStringArrayList(usesOptionalLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006376 usesLibraryFiles = dest.readStringArray();
6377
Svet Ganov67882122016-12-11 16:36:34 -08006378 final int libCount = dest.readInt();
6379 if (libCount > 0) {
6380 usesStaticLibraries = new ArrayList<>(libCount);
6381 dest.readStringList(usesStaticLibraries);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006382 internStringArrayList(usesStaticLibraries);
Svet Ganov67882122016-12-11 16:36:34 -08006383 usesStaticLibrariesVersions = new int[libCount];
6384 dest.readIntArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006385 usesStaticLibrariesCertDigests = new String[libCount][];
6386 for (int i = 0; i < libCount; i++) {
6387 usesStaticLibrariesCertDigests[i] = dest.createStringArray();
6388 }
Svet Ganov67882122016-12-11 16:36:34 -08006389 }
6390
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006391 preferredActivityFilters = new ArrayList<>();
6392 dest.readParcelableList(preferredActivityFilters, boot);
6393 if (preferredActivityFilters.size() == 0) {
6394 preferredActivityFilters = null;
6395 }
6396
6397 mOriginalPackages = dest.createStringArrayList();
6398 mRealPackage = dest.readString();
6399 mAdoptPermissions = dest.createStringArrayList();
6400 mAppMetaData = dest.readBundle();
6401 mVersionCode = dest.readInt();
6402 mVersionName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006403 if (mVersionName != null) {
6404 mVersionName = mVersionName.intern();
6405 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006406 mSharedUserId = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006407 if (mSharedUserId != null) {
6408 mSharedUserId = mSharedUserId.intern();
6409 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006410 mSharedUserLabel = dest.readInt();
6411
6412 mSignatures = (Signature[]) dest.readParcelableArray(boot, Signature.class);
6413 mCertificates = (Certificate[][]) dest.readSerializable();
6414
6415 mPreferredOrder = dest.readInt();
6416
6417 // long[] packageUsageTimeMillis is not persisted because it isn't information that
6418 // is parsed from the APK.
6419
6420 // Object mExtras is not persisted because it is not information that is read from
6421 // the APK, rather, it is supplied by callers.
6422
6423
6424 configPreferences = new ArrayList<>();
6425 dest.readParcelableList(configPreferences, boot);
6426 if (configPreferences.size() == 0) {
6427 configPreferences = null;
6428 }
6429
6430 reqFeatures = new ArrayList<>();
6431 dest.readParcelableList(reqFeatures, boot);
6432 if (reqFeatures.size() == 0) {
6433 reqFeatures = null;
6434 }
6435
6436 featureGroups = new ArrayList<>();
6437 dest.readParcelableList(featureGroups, boot);
6438 if (featureGroups.size() == 0) {
6439 featureGroups = null;
6440 }
6441
6442 installLocation = dest.readInt();
6443 coreApp = (dest.readInt() == 1);
6444 mRequiredForAllUsers = (dest.readInt() == 1);
6445 mRestrictedAccountType = dest.readString();
6446 mRequiredAccountType = dest.readString();
6447 mOverlayTarget = dest.readString();
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006448 mOverlayPriority = dest.readInt();
Jaekyun Seok04342892017-03-02 15:24:19 +09006449 mIsStaticOverlay = (dest.readInt() == 1);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006450 mTrustedOverlay = (dest.readInt() == 1);
6451 mSigningKeys = (ArraySet<PublicKey>) dest.readArraySet(boot);
6452 mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
6453
6454 mKeySetMapping = readKeySetMapping(dest);
6455
6456 cpuAbiOverride = dest.readString();
6457 use32bitAbi = (dest.readInt() == 1);
6458 restrictUpdateHash = dest.createByteArray();
Chad Brubaker49f24c62017-04-05 13:08:21 -07006459 visibleToInstantApps = dest.readInt() == 1;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006460 }
6461
Narayan Kamath07ac1442017-02-10 15:08:07 +00006462 private static void internStringArrayList(List<String> list) {
6463 if (list != null) {
6464 final int N = list.size();
6465 for (int i = 0; i < N; ++i) {
6466 list.set(i, list.get(i).intern());
6467 }
6468 }
6469 }
6470
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006471 /**
6472 * Sets the package owner and the the {@code applicationInfo} for every component
6473 * owner by this package.
6474 */
6475 private void fixupOwner(List<? extends Component<?>> list) {
6476 if (list != null) {
6477 for (Component<?> c : list) {
6478 c.owner = this;
6479 if (c instanceof Activity) {
6480 ((Activity) c).info.applicationInfo = this.applicationInfo;
6481 } else if (c instanceof Service) {
6482 ((Service) c).info.applicationInfo = this.applicationInfo;
6483 } else if (c instanceof Provider) {
6484 ((Provider) c).info.applicationInfo = this.applicationInfo;
6485 }
6486 }
6487 }
6488 }
6489
6490 @Override
6491 public void writeToParcel(Parcel dest, int flags) {
6492 dest.writeString(packageName);
Svet Ganov67882122016-12-11 16:36:34 -08006493 dest.writeString(manifestPackageName);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006494 dest.writeStringArray(splitNames);
6495 dest.writeString(volumeUuid);
6496 dest.writeString(codePath);
6497 dest.writeString(baseCodePath);
6498 dest.writeStringArray(splitCodePaths);
6499 dest.writeInt(baseRevisionCode);
6500 dest.writeIntArray(splitRevisionCodes);
6501 dest.writeIntArray(splitFlags);
6502 dest.writeIntArray(splitPrivateFlags);
6503 dest.writeInt(baseHardwareAccelerated ? 1 : 0);
6504 dest.writeParcelable(applicationInfo, flags);
6505
6506 dest.writeParcelableList(permissions, flags);
6507 dest.writeParcelableList(permissionGroups, flags);
6508 dest.writeParcelableList(activities, flags);
6509 dest.writeParcelableList(receivers, flags);
6510 dest.writeParcelableList(providers, flags);
6511 dest.writeParcelableList(services, flags);
6512 dest.writeParcelableList(instrumentation, flags);
6513
6514 dest.writeStringList(requestedPermissions);
6515 dest.writeStringList(protectedBroadcasts);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07006516
6517 // TODO: This doesn't work: b/64295061
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006518 dest.writeParcelable(parentPackage, flags);
6519 dest.writeParcelableList(childPackages, flags);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07006520
Svet Ganov67882122016-12-11 16:36:34 -08006521 dest.writeString(staticSharedLibName);
6522 dest.writeInt(staticSharedLibVersion);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006523 dest.writeStringList(libraryNames);
6524 dest.writeStringList(usesLibraries);
6525 dest.writeStringList(usesOptionalLibraries);
6526 dest.writeStringArray(usesLibraryFiles);
6527
Svet Ganov67882122016-12-11 16:36:34 -08006528 if (ArrayUtils.isEmpty(usesStaticLibraries)) {
6529 dest.writeInt(-1);
6530 } else {
6531 dest.writeInt(usesStaticLibraries.size());
6532 dest.writeStringList(usesStaticLibraries);
6533 dest.writeIntArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006534 for (String[] usesStaticLibrariesCertDigest : usesStaticLibrariesCertDigests) {
6535 dest.writeStringArray(usesStaticLibrariesCertDigest);
6536 }
Svet Ganov67882122016-12-11 16:36:34 -08006537 }
6538
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006539 dest.writeParcelableList(preferredActivityFilters, flags);
6540
6541 dest.writeStringList(mOriginalPackages);
6542 dest.writeString(mRealPackage);
6543 dest.writeStringList(mAdoptPermissions);
6544 dest.writeBundle(mAppMetaData);
6545 dest.writeInt(mVersionCode);
6546 dest.writeString(mVersionName);
6547 dest.writeString(mSharedUserId);
6548 dest.writeInt(mSharedUserLabel);
6549
6550 dest.writeParcelableArray(mSignatures, flags);
6551 dest.writeSerializable(mCertificates);
6552
6553 dest.writeInt(mPreferredOrder);
6554
6555 // long[] packageUsageTimeMillis is not persisted because it isn't information that
6556 // is parsed from the APK.
6557
6558 // Object mExtras is not persisted because it is not information that is read from
6559 // the APK, rather, it is supplied by callers.
6560
6561 dest.writeParcelableList(configPreferences, flags);
6562 dest.writeParcelableList(reqFeatures, flags);
6563 dest.writeParcelableList(featureGroups, flags);
6564
6565 dest.writeInt(installLocation);
6566 dest.writeInt(coreApp ? 1 : 0);
6567 dest.writeInt(mRequiredForAllUsers ? 1 : 0);
6568 dest.writeString(mRestrictedAccountType);
6569 dest.writeString(mRequiredAccountType);
6570 dest.writeString(mOverlayTarget);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006571 dest.writeInt(mOverlayPriority);
Jaekyun Seok04342892017-03-02 15:24:19 +09006572 dest.writeInt(mIsStaticOverlay ? 1 : 0);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006573 dest.writeInt(mTrustedOverlay ? 1 : 0);
6574 dest.writeArraySet(mSigningKeys);
6575 dest.writeArraySet(mUpgradeKeySets);
6576 writeKeySetMapping(dest, mKeySetMapping);
6577 dest.writeString(cpuAbiOverride);
6578 dest.writeInt(use32bitAbi ? 1 : 0);
6579 dest.writeByteArray(restrictUpdateHash);
Chad Brubaker49f24c62017-04-05 13:08:21 -07006580 dest.writeInt(visibleToInstantApps ? 1 : 0);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006581 }
6582
6583
6584 /**
6585 * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
6586 */
6587 private static void writeKeySetMapping(
6588 Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
6589 if (keySetMapping == null) {
6590 dest.writeInt(-1);
6591 return;
6592 }
6593
6594 final int N = keySetMapping.size();
6595 dest.writeInt(N);
6596
6597 for (int i = 0; i < N; i++) {
6598 dest.writeString(keySetMapping.keyAt(i));
6599 ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
6600 if (keys == null) {
6601 dest.writeInt(-1);
6602 continue;
6603 }
6604
6605 final int M = keys.size();
6606 dest.writeInt(M);
6607 for (int j = 0; j < M; j++) {
6608 dest.writeSerializable(keys.valueAt(j));
6609 }
6610 }
6611 }
6612
6613 /**
6614 * Reads a keyset mapping from the given parcel at the given data position. May return
6615 * {@code null} if the serialized mapping was {@code null}.
6616 */
6617 private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
6618 final int N = in.readInt();
6619 if (N == -1) {
6620 return null;
6621 }
6622
6623 ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
6624 for (int i = 0; i < N; ++i) {
6625 String key = in.readString();
6626 final int M = in.readInt();
6627 if (M == -1) {
6628 keySetMapping.put(key, null);
6629 continue;
6630 }
6631
6632 ArraySet<PublicKey> keys = new ArraySet<>(M);
6633 for (int j = 0; j < M; ++j) {
6634 PublicKey pk = (PublicKey) in.readSerializable();
6635 keys.add(pk);
6636 }
6637
6638 keySetMapping.put(key, keys);
6639 }
6640
6641 return keySetMapping;
6642 }
6643
6644 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
6645 public Package createFromParcel(Parcel in) {
6646 return new Package(in);
6647 }
6648
6649 public Package[] newArray(int size) {
6650 return new Package[size];
6651 }
6652 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006653 }
6654
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006655 public static abstract class Component<II extends IntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006656 public final ArrayList<II> intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006657 public final String className;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006659 public Bundle metaData;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006660 public Package owner;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006661
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006662 ComponentName componentName;
6663 String componentShortName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006664
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006665 public Component(Package _owner) {
6666 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006667 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006668 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006669 }
6670
6671 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
6672 owner = args.owner;
6673 intents = new ArrayList<II>(0);
Todd Kennedybb8a42d2016-06-02 14:13:56 -07006674 if (parsePackageItemInfo(args.owner, outInfo, args.outError, args.tag, args.sa,
6675 true /*nameRequired*/, args.nameRes, args.labelRes, args.iconRes,
6676 args.roundIconRes, args.logoRes, args.bannerRes)) {
6677 className = outInfo.name;
6678 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006679 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006680 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006681 }
6682
6683 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
6684 this(args, (PackageItemInfo)outInfo);
6685 if (args.outError[0] != null) {
6686 return;
6687 }
6688
6689 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07006690 CharSequence pname;
6691 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07006692 pname = args.sa.getNonConfigurationString(args.processRes,
6693 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07006694 } else {
6695 // Some older apps have been seen to use a resource reference
6696 // here that on older builds was ignored (with a warning). We
6697 // need to continue to do this for them so they don't break.
6698 pname = args.sa.getNonResourceString(args.processRes);
6699 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006700 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07006701 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006702 args.flags, args.sepProcesses, args.outError);
6703 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006704
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08006705 if (args.descriptionRes != 0) {
6706 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
6707 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006708
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006709 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006710 }
6711
6712 public Component(Component<II> clone) {
6713 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006714 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006715 className = clone.className;
6716 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006717 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006718 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006719
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006720 public ComponentName getComponentName() {
6721 if (componentName != null) {
6722 return componentName;
6723 }
6724 if (className != null) {
6725 componentName = new ComponentName(owner.applicationInfo.packageName,
6726 className);
6727 }
6728 return componentName;
6729 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07006730
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006731 protected Component(Parcel in) {
6732 className = in.readString();
6733 metaData = in.readBundle();
6734 intents = createIntentsList(in);
6735
6736 owner = null;
6737 }
6738
6739 protected void writeToParcel(Parcel dest, int flags) {
6740 dest.writeString(className);
6741 dest.writeBundle(metaData);
6742
6743 writeIntentsList(intents, dest, flags);
6744 }
6745
6746 /**
6747 * <p>
6748 * Implementation note: The serialized form for the intent list also contains the name
6749 * of the concrete class that's stored in the list, and assumes that every element of the
6750 * list is of the same type. This is very similar to the original parcelable mechanism.
6751 * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable
6752 * and is public API. It also declares Parcelable related methods as final which means
6753 * we can't extend them. The approach of using composition instead of inheritance leads to
6754 * a large set of cascading changes in the PackageManagerService, which seem undesirable.
6755 *
6756 * <p>
6757 * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up
6758 * to make sure their owner fields are consistent. See {@code fixupOwner}.
6759 */
6760 private static void writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out,
6761 int flags) {
6762 if (list == null) {
6763 out.writeInt(-1);
6764 return;
6765 }
6766
6767 final int N = list.size();
6768 out.writeInt(N);
6769
6770 // Don't bother writing the component name if the list is empty.
6771 if (N > 0) {
6772 IntentInfo info = list.get(0);
6773 out.writeString(info.getClass().getName());
6774
6775 for (int i = 0; i < N;i++) {
6776 list.get(i).writeIntentInfoToParcel(out, flags);
6777 }
6778 }
6779 }
6780
6781 private static <T extends IntentInfo> ArrayList<T> createIntentsList(Parcel in) {
6782 int N = in.readInt();
6783 if (N == -1) {
6784 return null;
6785 }
6786
6787 if (N == 0) {
6788 return new ArrayList<>(0);
6789 }
6790
6791 String componentName = in.readString();
6792 final ArrayList<T> intentsList;
6793 try {
6794 final Class<T> cls = (Class<T>) Class.forName(componentName);
6795 final Constructor<T> cons = cls.getConstructor(Parcel.class);
6796
6797 intentsList = new ArrayList<>(N);
6798 for (int i = 0; i < N; ++i) {
6799 intentsList.add(cons.newInstance(in));
6800 }
6801 } catch (ReflectiveOperationException ree) {
6802 throw new AssertionError("Unable to construct intent list for: " + componentName);
6803 }
6804
6805 return intentsList;
6806 }
6807
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07006808 public void appendComponentShortName(StringBuilder sb) {
6809 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006810 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07006811
6812 public void printComponentShortName(PrintWriter pw) {
6813 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
6814 }
6815
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006816 public void setPackageName(String packageName) {
6817 componentName = null;
6818 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006819 }
6820 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006821
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006822 public final static class Permission extends Component<IntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006823 public final PermissionInfo info;
6824 public boolean tree;
6825 public PermissionGroup group;
6826
6827 public Permission(Package _owner) {
6828 super(_owner);
6829 info = new PermissionInfo();
6830 }
6831
6832 public Permission(Package _owner, PermissionInfo _info) {
6833 super(_owner);
6834 info = _info;
6835 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006836
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006837 public void setPackageName(String packageName) {
6838 super.setPackageName(packageName);
6839 info.packageName = packageName;
6840 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006841
6842 public String toString() {
6843 return "Permission{"
6844 + Integer.toHexString(System.identityHashCode(this))
6845 + " " + info.name + "}";
6846 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006847
6848 @Override
6849 public int describeContents() {
6850 return 0;
6851 }
6852
6853 @Override
6854 public void writeToParcel(Parcel dest, int flags) {
6855 super.writeToParcel(dest, flags);
6856 dest.writeParcelable(info, flags);
6857 dest.writeInt(tree ? 1 : 0);
6858 dest.writeParcelable(group, flags);
6859 }
6860
6861 private Permission(Parcel in) {
6862 super(in);
6863 final ClassLoader boot = Object.class.getClassLoader();
6864 info = in.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006865 if (info.group != null) {
6866 info.group = info.group.intern();
6867 }
6868
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006869 tree = (in.readInt() == 1);
6870 group = in.readParcelable(boot);
6871 }
6872
6873 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Permission>() {
6874 public Permission createFromParcel(Parcel in) {
6875 return new Permission(in);
6876 }
6877
6878 public Permission[] newArray(int size) {
6879 return new Permission[size];
6880 }
6881 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006882 }
6883
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006884 public final static class PermissionGroup extends Component<IntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006885 public final PermissionGroupInfo info;
6886
6887 public PermissionGroup(Package _owner) {
6888 super(_owner);
6889 info = new PermissionGroupInfo();
6890 }
6891
6892 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
6893 super(_owner);
6894 info = _info;
6895 }
6896
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006897 public void setPackageName(String packageName) {
6898 super.setPackageName(packageName);
6899 info.packageName = packageName;
6900 }
6901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006902 public String toString() {
6903 return "PermissionGroup{"
6904 + Integer.toHexString(System.identityHashCode(this))
6905 + " " + info.name + "}";
6906 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006907
6908 @Override
6909 public int describeContents() {
6910 return 0;
6911 }
6912
6913 @Override
6914 public void writeToParcel(Parcel dest, int flags) {
6915 super.writeToParcel(dest, flags);
6916 dest.writeParcelable(info, flags);
6917 }
6918
6919 private PermissionGroup(Parcel in) {
6920 super(in);
6921 info = in.readParcelable(Object.class.getClassLoader());
6922 }
6923
6924 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<PermissionGroup>() {
6925 public PermissionGroup createFromParcel(Parcel in) {
6926 return new PermissionGroup(in);
6927 }
6928
6929 public PermissionGroup[] newArray(int size) {
6930 return new PermissionGroup[size];
6931 }
6932 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006933 }
6934
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006935 private static boolean copyNeeded(int flags, Package p,
6936 PackageUserState state, Bundle metaData, int userId) {
Xiaohui Chen98404fd2015-08-17 16:09:02 -07006937 if (userId != UserHandle.USER_SYSTEM) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006938 // We always need to copy for other users, since we need
6939 // to fix up the uid.
6940 return true;
6941 }
6942 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
6943 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07006944 if (p.applicationInfo.enabled != enabled) {
6945 return true;
6946 }
6947 }
Rubin Xubf67c9c2016-04-20 17:09:38 +01006948 boolean suspended = (p.applicationInfo.flags & FLAG_SUSPENDED) != 0;
6949 if (state.suspended != suspended) {
6950 return true;
6951 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07006952 if (!state.installed || state.hidden) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006953 return true;
6954 }
6955 if (state.stopped) {
6956 return true;
6957 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08006958 if (state.instantApp != p.applicationInfo.isInstantApp()) {
6959 return true;
6960 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006961 if ((flags & PackageManager.GET_META_DATA) != 0
6962 && (metaData != null || p.mAppMetaData != null)) {
6963 return true;
6964 }
6965 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
6966 && p.usesLibraryFiles != null) {
6967 return true;
6968 }
Svet Ganov67882122016-12-11 16:36:34 -08006969 if (p.staticSharedLibName != null) {
6970 return true;
6971 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006972 return false;
6973 }
6974
Dianne Hackborn7767eac2012-08-23 18:25:40 -07006975 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
6976 PackageUserState state) {
6977 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07006978 }
6979
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08006980 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
6981 PackageUserState state) {
6982 // CompatibilityMode is global state.
6983 if (!sCompatibilityModeEnabled) {
6984 ai.disableCompatibilityMode();
6985 }
6986 if (state.installed) {
6987 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
6988 } else {
6989 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
6990 }
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00006991 if (state.suspended) {
6992 ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
6993 } else {
6994 ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
6995 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08006996 if (state.instantApp) {
6997 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT;
6998 } else {
6999 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT;
7000 }
Todd Kennedy5eb5a7d2017-08-01 07:42:47 -07007001 if (state.virtualPreload) {
7002 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7003 } else {
7004 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7005 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007006 if (state.hidden) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007007 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007008 } else {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007009 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007010 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007011 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
7012 ai.enabled = true;
7013 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
7014 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
7015 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
7016 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
7017 ai.enabled = false;
7018 }
7019 ai.enabledSetting = state.enabled;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07007020 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7021 ai.category = state.categoryHint;
7022 }
Jeff Sharkey0078e1b2017-01-11 16:05:27 -07007023 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7024 ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
7025 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007026 ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
Todd Kennedyb2749472017-06-13 08:24:32 -07007027 ai.resourceDirs = state.overlayPaths;
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007028 }
7029
Amith Yamasani13593602012-03-22 16:16:17 -07007030 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007031 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007032 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007033 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007034 return null;
7035 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007036 if (!copyNeeded(flags, p, state, null, userId)
7037 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
7038 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
7039 // In this case it is safe to directly modify the internal ApplicationInfo state:
7040 // - CompatibilityMode is global state, so will be the same for every call.
7041 // - We only come in to here if the app should reported as installed; this is the
7042 // default state, and we will do a copy otherwise.
7043 // - The enable state will always be reported the same for the application across
7044 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
7045 // be doing a copy.
7046 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007047 return p.applicationInfo;
7048 }
7049
7050 // Make shallow copy so we can store the metadata/libraries safely
7051 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Jeff Sharkey15447792015-11-05 16:18:51 -08007052 ai.initForUser(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007053 if ((flags & PackageManager.GET_META_DATA) != 0) {
7054 ai.metaData = p.mAppMetaData;
7055 }
7056 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
7057 ai.sharedLibraryFiles = p.usesLibraryFiles;
7058 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007059 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007060 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007061 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007062 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007063 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007064 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007065 return ai;
7066 }
7067
Dianne Hackbornace27912014-09-18 18:38:30 -07007068 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
7069 PackageUserState state, int userId) {
7070 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007071 if (!checkUseInstalledOrHidden(flags, state, ai)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007072 return null;
7073 }
7074 // This is only used to return the ResolverActivity; we will just always
7075 // make a copy.
7076 ai = new ApplicationInfo(ai);
Jeff Sharkey15447792015-11-05 16:18:51 -08007077 ai.initForUser(userId);
Dianne Hackbornace27912014-09-18 18:38:30 -07007078 if (state.stopped) {
7079 ai.flags |= ApplicationInfo.FLAG_STOPPED;
7080 } else {
7081 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
7082 }
7083 updateApplicationInfo(ai, flags, state);
7084 return ai;
7085 }
7086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007087 public static final PermissionInfo generatePermissionInfo(
7088 Permission p, int flags) {
7089 if (p == null) return null;
7090 if ((flags&PackageManager.GET_META_DATA) == 0) {
7091 return p.info;
7092 }
7093 PermissionInfo pi = new PermissionInfo(p.info);
7094 pi.metaData = p.metaData;
7095 return pi;
7096 }
7097
7098 public static final PermissionGroupInfo generatePermissionGroupInfo(
7099 PermissionGroup pg, int flags) {
7100 if (pg == null) return null;
7101 if ((flags&PackageManager.GET_META_DATA) == 0) {
7102 return pg.info;
7103 }
7104 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
7105 pgi.metaData = pg.metaData;
7106 return pgi;
7107 }
7108
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007109 public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007110 public final ActivityInfo info;
Bryce Lee22571db2017-07-07 15:54:18 -07007111 private boolean mHasMaxAspectRatio;
7112
7113 private boolean hasMaxAspectRatio() {
7114 return mHasMaxAspectRatio;
7115 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007116
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007117 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
7118 super(args, _info);
7119 info = _info;
7120 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007121 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007122
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007123 public void setPackageName(String packageName) {
7124 super.setPackageName(packageName);
7125 info.packageName = packageName;
7126 }
7127
Bryce Lee22571db2017-07-07 15:54:18 -07007128
7129 private void setMaxAspectRatio(float maxAspectRatio) {
7130 if (info.resizeMode == RESIZE_MODE_RESIZEABLE
7131 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
7132 // Resizeable activities can be put in any aspect ratio.
7133 return;
7134 }
7135
7136 if (maxAspectRatio < 1.0f && maxAspectRatio != 0) {
7137 // Ignore any value lesser than 1.0.
7138 return;
7139 }
7140
7141 info.maxAspectRatio = maxAspectRatio;
7142 mHasMaxAspectRatio = true;
7143 }
7144
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007145 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007146 StringBuilder sb = new StringBuilder(128);
7147 sb.append("Activity{");
7148 sb.append(Integer.toHexString(System.identityHashCode(this)));
7149 sb.append(' ');
7150 appendComponentShortName(sb);
7151 sb.append('}');
7152 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007153 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007154
7155 @Override
7156 public int describeContents() {
7157 return 0;
7158 }
7159
7160 @Override
7161 public void writeToParcel(Parcel dest, int flags) {
7162 super.writeToParcel(dest, flags);
7163 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
Bryce Lee22571db2017-07-07 15:54:18 -07007164 dest.writeBoolean(mHasMaxAspectRatio);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007165 }
7166
7167 private Activity(Parcel in) {
7168 super(in);
7169 info = in.readParcelable(Object.class.getClassLoader());
Bryce Lee22571db2017-07-07 15:54:18 -07007170 mHasMaxAspectRatio = in.readBoolean();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007171
7172 for (ActivityIntentInfo aii : intents) {
7173 aii.activity = this;
7174 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007175
7176 if (info.permission != null) {
7177 info.permission = info.permission.intern();
7178 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007179 }
7180
7181 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Activity>() {
7182 public Activity createFromParcel(Parcel in) {
7183 return new Activity(in);
7184 }
7185
7186 public Activity[] newArray(int size) {
7187 return new Activity[size];
7188 }
7189 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007190 }
7191
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007192 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
7193 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007194 if (a == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007195 if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007196 return null;
7197 }
7198 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007199 updateApplicationInfo(a.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007200 return a.info;
7201 }
7202 // Make shallow copies so we can store the metadata safely
7203 ActivityInfo ai = new ActivityInfo(a.info);
7204 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007205 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007206 return ai;
7207 }
7208
Dianne Hackbornace27912014-09-18 18:38:30 -07007209 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
7210 PackageUserState state, int userId) {
7211 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007212 if (!checkUseInstalledOrHidden(flags, state, ai.applicationInfo)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007213 return null;
7214 }
7215 // This is only used to return the ResolverActivity; we will just always
7216 // make a copy.
7217 ai = new ActivityInfo(ai);
7218 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
7219 return ai;
7220 }
7221
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007222 public final static class Service extends Component<ServiceIntentInfo> implements Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007223 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007224
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007225 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
7226 super(args, _info);
7227 info = _info;
7228 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007229 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007230
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007231 public void setPackageName(String packageName) {
7232 super.setPackageName(packageName);
7233 info.packageName = packageName;
7234 }
7235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007236 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007237 StringBuilder sb = new StringBuilder(128);
7238 sb.append("Service{");
7239 sb.append(Integer.toHexString(System.identityHashCode(this)));
7240 sb.append(' ');
7241 appendComponentShortName(sb);
7242 sb.append('}');
7243 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007244 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007245
7246 @Override
7247 public int describeContents() {
7248 return 0;
7249 }
7250
7251 @Override
7252 public void writeToParcel(Parcel dest, int flags) {
7253 super.writeToParcel(dest, flags);
7254 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
7255 }
7256
7257 private Service(Parcel in) {
7258 super(in);
7259 info = in.readParcelable(Object.class.getClassLoader());
7260
7261 for (ServiceIntentInfo aii : intents) {
7262 aii.service = this;
7263 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007264
7265 if (info.permission != null) {
7266 info.permission = info.permission.intern();
7267 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007268 }
7269
7270 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Service>() {
7271 public Service createFromParcel(Parcel in) {
7272 return new Service(in);
7273 }
7274
7275 public Service[] newArray(int size) {
7276 return new Service[size];
7277 }
7278 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007279 }
7280
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007281 public static final ServiceInfo generateServiceInfo(Service s, int flags,
7282 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007283 if (s == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007284 if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007285 return null;
7286 }
7287 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007288 updateApplicationInfo(s.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007289 return s.info;
7290 }
7291 // Make shallow copies so we can store the metadata safely
7292 ServiceInfo si = new ServiceInfo(s.info);
7293 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007294 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007295 return si;
7296 }
7297
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007298 public final static class Provider extends Component<ProviderIntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007299 public final ProviderInfo info;
7300 public boolean syncable;
7301
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007302 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
7303 super(args, _info);
7304 info = _info;
7305 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007306 syncable = false;
7307 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007309 public Provider(Provider existingProvider) {
7310 super(existingProvider);
7311 this.info = existingProvider.info;
7312 this.syncable = existingProvider.syncable;
7313 }
7314
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007315 public void setPackageName(String packageName) {
7316 super.setPackageName(packageName);
7317 info.packageName = packageName;
7318 }
7319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007320 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007321 StringBuilder sb = new StringBuilder(128);
7322 sb.append("Provider{");
7323 sb.append(Integer.toHexString(System.identityHashCode(this)));
7324 sb.append(' ');
7325 appendComponentShortName(sb);
7326 sb.append('}');
7327 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007328 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007329
7330 @Override
7331 public int describeContents() {
7332 return 0;
7333 }
7334
7335 @Override
7336 public void writeToParcel(Parcel dest, int flags) {
7337 super.writeToParcel(dest, flags);
7338 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
7339 dest.writeInt((syncable) ? 1 : 0);
7340 }
7341
7342 private Provider(Parcel in) {
7343 super(in);
7344 info = in.readParcelable(Object.class.getClassLoader());
7345 syncable = (in.readInt() == 1);
7346
7347 for (ProviderIntentInfo aii : intents) {
7348 aii.provider = this;
7349 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007350
7351 if (info.readPermission != null) {
7352 info.readPermission = info.readPermission.intern();
7353 }
7354
7355 if (info.writePermission != null) {
7356 info.writePermission = info.writePermission.intern();
7357 }
7358
7359 if (info.authority != null) {
7360 info.authority = info.authority.intern();
7361 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007362 }
7363
7364 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Provider>() {
7365 public Provider createFromParcel(Parcel in) {
7366 return new Provider(in);
7367 }
7368
7369 public Provider[] newArray(int size) {
7370 return new Provider[size];
7371 }
7372 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007373 }
7374
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007375 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
7376 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007377 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007378 if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007379 return null;
7380 }
7381 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007382 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007383 || p.info.uriPermissionPatterns == null)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007384 updateApplicationInfo(p.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007385 return p.info;
7386 }
7387 // Make shallow copies so we can store the metadata safely
7388 ProviderInfo pi = new ProviderInfo(p.info);
7389 pi.metaData = p.metaData;
7390 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
7391 pi.uriPermissionPatterns = null;
7392 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007393 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007394 return pi;
7395 }
7396
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007397 public final static class Instrumentation extends Component<IntentInfo> implements
7398 Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007399 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007400
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007401 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
7402 super(args, _info);
7403 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007404 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007405
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007406 public void setPackageName(String packageName) {
7407 super.setPackageName(packageName);
7408 info.packageName = packageName;
7409 }
7410
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007411 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007412 StringBuilder sb = new StringBuilder(128);
7413 sb.append("Instrumentation{");
7414 sb.append(Integer.toHexString(System.identityHashCode(this)));
7415 sb.append(' ');
7416 appendComponentShortName(sb);
7417 sb.append('}');
7418 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007419 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007420
7421 @Override
7422 public int describeContents() {
7423 return 0;
7424 }
7425
7426 @Override
7427 public void writeToParcel(Parcel dest, int flags) {
7428 super.writeToParcel(dest, flags);
7429 dest.writeParcelable(info, flags);
7430 }
7431
7432 private Instrumentation(Parcel in) {
7433 super(in);
7434 info = in.readParcelable(Object.class.getClassLoader());
Narayan Kamath07ac1442017-02-10 15:08:07 +00007435
7436 if (info.targetPackage != null) {
7437 info.targetPackage = info.targetPackage.intern();
7438 }
7439
Dianne Hackborn1be53542017-04-28 13:36:00 -07007440 if (info.targetProcesses != null) {
7441 info.targetProcesses = info.targetProcesses.intern();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007442 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007443 }
7444
7445 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Instrumentation>() {
7446 public Instrumentation createFromParcel(Parcel in) {
7447 return new Instrumentation(in);
7448 }
7449
7450 public Instrumentation[] newArray(int size) {
7451 return new Instrumentation[size];
7452 }
7453 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007454 }
7455
7456 public static final InstrumentationInfo generateInstrumentationInfo(
7457 Instrumentation i, int flags) {
7458 if (i == null) return null;
7459 if ((flags&PackageManager.GET_META_DATA) == 0) {
7460 return i.info;
7461 }
7462 InstrumentationInfo ii = new InstrumentationInfo(i.info);
7463 ii.metaData = i.metaData;
7464 return ii;
7465 }
7466
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007467 public static abstract class IntentInfo extends IntentFilter {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007468 public boolean hasDefault;
7469 public int labelRes;
7470 public CharSequence nonLocalizedLabel;
7471 public int icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07007472 public int logo;
Jose Limaf78e3122014-03-06 12:13:15 -08007473 public int banner;
Dianne Hackbornb09491f2013-07-22 15:30:11 -07007474 public int preferred;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007475
7476 protected IntentInfo() {
7477 }
7478
7479 protected IntentInfo(Parcel dest) {
7480 super(dest);
7481 hasDefault = (dest.readInt() == 1);
7482 labelRes = dest.readInt();
7483 nonLocalizedLabel = dest.readCharSequence();
7484 icon = dest.readInt();
7485 logo = dest.readInt();
7486 banner = dest.readInt();
7487 preferred = dest.readInt();
7488 }
7489
7490
7491 public void writeIntentInfoToParcel(Parcel dest, int flags) {
7492 super.writeToParcel(dest, flags);
7493 dest.writeInt(hasDefault ? 1 : 0);
7494 dest.writeInt(labelRes);
7495 dest.writeCharSequence(nonLocalizedLabel);
7496 dest.writeInt(icon);
7497 dest.writeInt(logo);
7498 dest.writeInt(banner);
7499 dest.writeInt(preferred);
7500 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007501 }
7502
7503 public final static class ActivityIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007504 public Activity activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007505
7506 public ActivityIntentInfo(Activity _activity) {
7507 activity = _activity;
7508 }
7509
7510 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007511 StringBuilder sb = new StringBuilder(128);
7512 sb.append("ActivityIntentInfo{");
7513 sb.append(Integer.toHexString(System.identityHashCode(this)));
7514 sb.append(' ');
7515 activity.appendComponentShortName(sb);
7516 sb.append('}');
7517 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007518 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007519
7520 public ActivityIntentInfo(Parcel in) {
7521 super(in);
7522 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007523 }
7524
7525 public final static class ServiceIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007526 public Service service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007527
7528 public ServiceIntentInfo(Service _service) {
7529 service = _service;
7530 }
7531
7532 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007533 StringBuilder sb = new StringBuilder(128);
7534 sb.append("ServiceIntentInfo{");
7535 sb.append(Integer.toHexString(System.identityHashCode(this)));
7536 sb.append(' ');
7537 service.appendComponentShortName(sb);
7538 sb.append('}');
7539 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007540 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007541
7542 public ServiceIntentInfo(Parcel in) {
7543 super(in);
7544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007545 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007546
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007547 public static final class ProviderIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007548 public Provider provider;
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007549
7550 public ProviderIntentInfo(Provider provider) {
7551 this.provider = provider;
7552 }
7553
7554 public String toString() {
7555 StringBuilder sb = new StringBuilder(128);
7556 sb.append("ProviderIntentInfo{");
7557 sb.append(Integer.toHexString(System.identityHashCode(this)));
7558 sb.append(' ');
7559 provider.appendComponentShortName(sb);
7560 sb.append('}');
7561 return sb.toString();
7562 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007563
7564 public ProviderIntentInfo(Parcel in) {
7565 super(in);
7566 }
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007567 }
7568
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007569 /**
7570 * @hide
7571 */
7572 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
7573 sCompatibilityModeEnabled = compatibilityModeEnabled;
7574 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07007575
Jeff Sharkey275e0852014-06-17 18:18:49 -07007576 private static AtomicReference<byte[]> sBuffer = new AtomicReference<byte[]>();
7577
7578 public static long readFullyIgnoringContents(InputStream in) throws IOException {
7579 byte[] buffer = sBuffer.getAndSet(null);
7580 if (buffer == null) {
7581 buffer = new byte[4096];
7582 }
7583
7584 int n = 0;
7585 int count = 0;
7586 while ((n = in.read(buffer, 0, buffer.length)) != -1) {
7587 count += n;
7588 }
7589
7590 sBuffer.set(buffer);
7591 return count;
7592 }
7593
7594 public static void closeQuietly(StrictJarFile jarFile) {
7595 if (jarFile != null) {
7596 try {
7597 jarFile.close();
7598 } catch (Exception ignored) {
7599 }
7600 }
7601 }
7602
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07007603 public static class PackageParserException extends Exception {
7604 public final int error;
7605
7606 public PackageParserException(int error, String detailMessage) {
7607 super(detailMessage);
7608 this.error = error;
7609 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07007610
7611 public PackageParserException(int error, String detailMessage, Throwable throwable) {
7612 super(detailMessage, throwable);
7613 this.error = error;
7614 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07007615 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007616}