blob: 3bb812b7ac8318690bd448dd576e6e39465bd40e [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;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070035import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
36import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
37import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070038import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -070039import static android.os.Build.VERSION_CODES.O;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070040import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
Robert Carr427ba4f2017-07-17 18:37:06 -070041import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070042
Todd Kennedy232d29e2017-11-06 14:45:53 -080043import android.annotation.IntDef;
Alan Viverette82f4b263a2016-12-19 15:40:05 -050044import android.annotation.IntRange;
45import android.annotation.NonNull;
Fyodor Kupolov965fa692016-10-28 18:20:25 -070046import android.annotation.Nullable;
Alan Viverette82f4b263a2016-12-19 15:40:05 -050047import android.annotation.TestApi;
Dianne Hackborn852975d2014-08-22 17:42:43 -070048import android.app.ActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.content.ComponentName;
50import android.content.Intent;
51import android.content.IntentFilter;
Makoto Onuki4501c61d2017-07-27 15:56:40 -070052import android.content.pm.PackageParserCacheHelper.ReadHelper;
53import android.content.pm.PackageParserCacheHelper.WriteHelper;
Garrett Boyer52136662017-05-23 13:47:58 -070054import android.content.pm.split.DefaultSplitAssetLoader;
Adam Lesinski4e862812016-11-21 16:02:24 -080055import android.content.pm.split.SplitAssetDependencyLoader;
56import android.content.pm.split.SplitAssetLoader;
Adam Lesinskidcb3c652017-01-23 12:58:11 -080057import android.content.res.ApkAssets;
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;
Dan Cashmane92f8422017-12-08 14:02:51 -080088import android.util.apk.ApkSignatureVerifier;
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -070089import android.view.Gravity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070091import com.android.internal.R;
92import com.android.internal.annotations.VisibleForTesting;
Narayan Kamathf9419f02017-06-15 11:35:38 +010093import com.android.internal.os.ClassLoaderFactory;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070094import com.android.internal.util.ArrayUtils;
95import com.android.internal.util.XmlUtils;
96
97import libcore.io.IoUtils;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -070098import libcore.util.EmptyArray;
Svet Ganov087dce22017-09-07 15:42:16 -070099
Jeff Sharkey9bc89af2017-01-11 11:25:50 -0700100import org.xmlpull.v1.XmlPullParser;
101import org.xmlpull.v1.XmlPullParserException;
102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103import java.io.File;
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700104import java.io.FileDescriptor;
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;
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -0700107import java.io.PrintWriter;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800108import java.lang.annotation.Retention;
109import java.lang.annotation.RetentionPolicy;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000110import java.lang.reflect.Constructor;
Kenny Root05ca4c92011-09-15 10:36:25 -0700111import java.security.KeyFactory;
112import java.security.NoSuchAlgorithmException;
113import java.security.PublicKey;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800114import java.security.cert.CertificateException;
Kenny Root05ca4c92011-09-15 10:36:25 -0700115import java.security.spec.EncodedKeySpec;
116import java.security.spec.InvalidKeySpecException;
117import java.security.spec.X509EncodedKeySpec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118import java.util.ArrayList;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700119import java.util.Arrays;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700120import java.util.Collections;
121import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122import java.util.Iterator;
Kenny Root05ca4c92011-09-15 10:36:25 -0700123import java.util.List;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800124import java.util.Set;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -0600125import java.util.UUID;
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700126import java.util.concurrent.atomic.AtomicInteger;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127
128/**
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700129 * Parser for package files (APKs) on disk. This supports apps packaged either
130 * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
131 * APKs in a single directory.
132 * <p>
133 * Apps packaged as multiple APKs always consist of a single "base" APK (with a
134 * {@code null} split name) and zero or more "split" APKs (with unique split
135 * names). Any subset of those split APKs are a valid install, as long as the
136 * following constraints are met:
137 * <ul>
138 * <li>All APKs must have the exact same package name, version code, and signing
139 * certificates.
140 * <li>All APKs must have unique split names.
141 * <li>All installations must contain a single base APK.
142 * </ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700144 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 */
146public class PackageParser {
Kenny Rootd2d29252011-08-08 11:27:57 -0700147 private static final boolean DEBUG_JAR = false;
148 private static final boolean DEBUG_PARSER = false;
149 private static final boolean DEBUG_BACKUP = false;
Fyodor Kupolov28a988f2017-07-31 18:44:11 -0700150 private static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE;
151 private static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100;
Kenny Rootd2d29252011-08-08 11:27:57 -0700152
Svet Ganova3c4eb32017-04-19 23:51:33 -0700153 private static final String PROPERTY_CHILD_PACKAGES_ENABLED =
154 "persist.sys.child_packages_enabled";
155
Jeff Sharkey3f1790d2017-04-25 18:56:17 -0600156 private static final boolean MULTI_PACKAGE_APK_ENABLED = Build.IS_DEBUGGABLE &&
Garrett Boyer17041532017-08-01 14:11:02 -0700157 SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false);
Svet Ganova3c4eb32017-04-19 23:51:33 -0700158
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700159 private static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f;
160
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700161 // TODO: switch outError users to PackageParserException
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700162 // TODO: refactor "codePath" to "apkPath"
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700163
Kenny Rootbcc954d2011-08-08 16:19:08 -0700164 /** File name in an APK for the Android manifest. */
Dan Cashmane92f8422017-12-08 14:02:51 -0800165 public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
Kenny Rootbcc954d2011-08-08 16:19:08 -0700166
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700167 /** Path prefix for apps on expanded storage */
168 private static final String MNT_EXPAND = "/mnt/expand/";
169
Svet Ganov354cd3c2015-12-17 11:35:04 -0800170 private static final String TAG_MANIFEST = "manifest";
171 private static final String TAG_APPLICATION = "application";
Adam Lesinski4e862812016-11-21 16:02:24 -0800172 private static final String TAG_PACKAGE_VERIFIER = "package-verifier";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800173 private static final String TAG_OVERLAY = "overlay";
174 private static final String TAG_KEY_SETS = "key-sets";
175 private static final String TAG_PERMISSION_GROUP = "permission-group";
176 private static final String TAG_PERMISSION = "permission";
177 private static final String TAG_PERMISSION_TREE = "permission-tree";
178 private static final String TAG_USES_PERMISSION = "uses-permission";
179 private static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
180 private static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23";
181 private static final String TAG_USES_CONFIGURATION = "uses-configuration";
182 private static final String TAG_USES_FEATURE = "uses-feature";
183 private static final String TAG_FEATURE_GROUP = "feature-group";
184 private static final String TAG_USES_SDK = "uses-sdk";
185 private static final String TAG_SUPPORT_SCREENS = "supports-screens";
186 private static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
187 private static final String TAG_INSTRUMENTATION = "instrumentation";
188 private static final String TAG_ORIGINAL_PACKAGE = "original-package";
189 private static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
190 private static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
191 private static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
192 private static final String TAG_SUPPORTS_INPUT = "supports-input";
193 private static final String TAG_EAT_COMMENT = "eat-comment";
194 private static final String TAG_PACKAGE = "package";
Todd Kennedyfdd241a2016-04-28 12:26:53 -0700195 private static final String TAG_RESTRICT_UPDATE = "restrict-update";
Adam Lesinski4e862812016-11-21 16:02:24 -0800196 private static final String TAG_USES_SPLIT = "uses-split";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800197
Todd Kennedyfe7f38c32017-03-23 09:51:21 -0700198 // [b/36551762] STOPSHIP remove the ability to expose components via meta-data
Todd Kennedy752fb702017-03-21 16:28:10 -0700199 // Temporary workaround; allow meta-data to expose components to instant apps
200 private static final String META_DATA_INSTANT_APPS = "instantapps.clients.allowed";
201
Bryce Lee22571db2017-07-07 15:54:18 -0700202 private static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
203
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800204 /**
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700205 * Bit mask of all the valid bits that can be set in recreateOnConfigChanges.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800206 * @hide
207 */
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700208 private static final int RECREATE_ON_CONFIG_CHANGES_MASK =
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800209 ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC;
210
Svet Ganov354cd3c2015-12-17 11:35:04 -0800211 // These are the tags supported by child packages
212 private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>();
213 static {
214 CHILD_PACKAGE_TAGS.add(TAG_APPLICATION);
215 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION);
216 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_M);
217 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_23);
218 CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION);
219 CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE);
220 CHILD_PACKAGE_TAGS.add(TAG_FEATURE_GROUP);
221 CHILD_PACKAGE_TAGS.add(TAG_USES_SDK);
222 CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS);
223 CHILD_PACKAGE_TAGS.add(TAG_INSTRUMENTATION);
224 CHILD_PACKAGE_TAGS.add(TAG_USES_GL_TEXTURE);
225 CHILD_PACKAGE_TAGS.add(TAG_COMPATIBLE_SCREENS);
226 CHILD_PACKAGE_TAGS.add(TAG_SUPPORTS_INPUT);
227 CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
228 }
229
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700230 private static final boolean LOG_UNSAFE_BROADCASTS = false;
231
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700232 /**
233 * Total number of packages that were read from the cache. We use it only for logging.
234 */
235 public static final AtomicInteger sCachedPackageReadCount = new AtomicInteger();
236
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700237 // Set of broadcast actions that are safe for manifest receivers
238 private static final Set<String> SAFE_BROADCASTS = new ArraySet<>();
239 static {
240 SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED);
241 }
242
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700243 /** @hide */
Calin Juravle3fc56c32017-12-11 18:26:13 -0800244 public static final String APK_FILE_EXTENSION = ".apk";
245
246 /** @hide */
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700247 public static class NewPermissionInfo {
248 public final String name;
249 public final int sdkVersion;
250 public final int fileVersion;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700251
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700252 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
253 this.name = name;
254 this.sdkVersion = sdkVersion;
255 this.fileVersion = fileVersion;
256 }
257 }
Dianne Hackborn79245122012-03-12 10:51:26 -0700258
259 /** @hide */
260 public static class SplitPermissionInfo {
261 public final String rootPerm;
262 public final String[] newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700263 public final int targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700264
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700265 public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
Dianne Hackborn79245122012-03-12 10:51:26 -0700266 this.rootPerm = rootPerm;
267 this.newPerms = newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700268 this.targetSdk = targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700269 }
270 }
271
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700272 /**
273 * List of new permissions that have been added since 1.0.
274 * NOTE: These must be declared in SDK version order, with permissions
275 * added to older SDKs appearing before those added to newer SDKs.
Dianne Hackborn79245122012-03-12 10:51:26 -0700276 * If sdkVersion is 0, then this is not a permission that we want to
277 * automatically add to older apps, but we do want to allow it to be
278 * granted during a platform update.
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700279 * @hide
280 */
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700281 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
282 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -0700283 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700284 android.os.Build.VERSION_CODES.DONUT, 0),
285 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
286 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700287 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288
Dianne Hackborn79245122012-03-12 10:51:26 -0700289 /**
290 * List of permissions that have been split into more granular or dependent
291 * permissions.
292 * @hide
293 */
294 public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
295 new PackageParser.SplitPermissionInfo[] {
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700296 // READ_EXTERNAL_STORAGE is always required when an app requests
297 // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
298 // write access without read access. The hack here with the target
299 // target SDK version ensures that this grant is always done.
Dianne Hackborn79245122012-03-12 10:51:26 -0700300 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700301 new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700302 android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700303 new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
304 new String[] { android.Manifest.permission.READ_CALL_LOG },
305 android.os.Build.VERSION_CODES.JELLY_BEAN),
306 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
307 new String[] { android.Manifest.permission.WRITE_CALL_LOG },
308 android.os.Build.VERSION_CODES.JELLY_BEAN)
Dianne Hackborn79245122012-03-12 10:51:26 -0700309 };
310
Jeff Sharkey275e0852014-06-17 18:18:49 -0700311 /**
312 * @deprecated callers should move to explicitly passing around source path.
313 */
314 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 private String mArchiveSourcePath;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700318 private boolean mOnlyCoreApps;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700319 private DisplayMetrics mMetrics;
Dianne Hackborncd154e92017-02-28 17:37:35 -0800320 private Callback mCallback;
Narayan Kamath988149c2016-12-01 13:32:59 +0000321 private File mCacheDir;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700322
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700323 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700324 private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325
326 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
327
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700328 private static boolean sCompatibilityModeEnabled = true;
Amith Yamasani655d0e22013-06-12 14:19:10 -0700329 private static final int PARSE_DEFAULT_INSTALL_LOCATION =
330 PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Todd Kennedy11e45072017-01-25 13:24:21 -0800331 private static final int PARSE_DEFAULT_TARGET_SANDBOX = 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700332
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700333 static class ParsePackageItemArgs {
334 final Package owner;
335 final String[] outError;
336 final int nameRes;
337 final int labelRes;
338 final int iconRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700339 final int roundIconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700340 final int logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800341 final int bannerRes;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700342
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700343 String tag;
344 TypedArray sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700345
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700346 ParsePackageItemArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700347 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
348 int _bannerRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700349 owner = _owner;
350 outError = _outError;
351 nameRes = _nameRes;
352 labelRes = _labelRes;
353 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700354 logoRes = _logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800355 bannerRes = _bannerRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700356 roundIconRes = _roundIconRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700357 }
358 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700359
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000360 /** @hide */
361 @VisibleForTesting
362 public static class ParseComponentArgs extends ParsePackageItemArgs {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700363 final String[] sepProcesses;
364 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800365 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700366 final int enabledRes;
367 int flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700368
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000369 public ParseComponentArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700370 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
371 int _bannerRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800372 String[] _sepProcesses, int _processRes,
373 int _descriptionRes, int _enabledRes) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700374 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _roundIconRes, _logoRes,
375 _bannerRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700376 sepProcesses = _sepProcesses;
377 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800378 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700379 enabledRes = _enabledRes;
380 }
381 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800382
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700383 /**
Jeff Sharkey73767b92014-07-04 20:18:13 -0700384 * Lightweight parsed details about a single package.
385 */
386 public static class PackageLite {
387 public final String packageName;
388 public final int versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700389 public final int versionCodeMajor;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700390 public final int installLocation;
391 public final VerifierInfo[] verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700392
393 /** Names of any split APKs, ordered by parsed splitName */
394 public final String[] splitNames;
395
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800396 /** Names of any split APKs that are features. Ordered by splitName */
397 public final boolean[] isFeatureSplits;
398
Adam Lesinski4e862812016-11-21 16:02:24 -0800399 /** Dependencies of any split APKs, ordered by parsed splitName */
400 public final String[] usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800401 public final String[] configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800402
Jeff Sharkey73767b92014-07-04 20:18:13 -0700403 /**
404 * Path where this package was found on disk. For monolithic packages
405 * this is path to single base APK file; for cluster packages this is
406 * path to the cluster directory.
407 */
408 public final String codePath;
409
410 /** Path of base APK */
411 public final String baseCodePath;
412 /** Paths of any split APKs, ordered by parsed splitName */
413 public final String[] splitCodePaths;
414
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800415 /** Revision code of base APK */
416 public final int baseRevisionCode;
417 /** Revision codes of any split APKs, ordered by parsed splitName */
418 public final int[] splitRevisionCodes;
419
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700420 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100421 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100422 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800423 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700424 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800425 public final boolean isolatedSplits;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100426
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700427 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800428 boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100429 String[] splitCodePaths, int[] splitRevisionCodes) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700430 this.packageName = baseApk.packageName;
431 this.versionCode = baseApk.versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700432 this.versionCodeMajor = baseApk.versionCodeMajor;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700433 this.installLocation = baseApk.installLocation;
434 this.verifiers = baseApk.verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700435 this.splitNames = splitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800436 this.isFeatureSplits = isFeatureSplits;
Adam Lesinski4e862812016-11-21 16:02:24 -0800437 this.usesSplitNames = usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800438 this.configForSplit = configForSplit;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700439 this.codePath = codePath;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700440 this.baseCodePath = baseApk.codePath;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700441 this.splitCodePaths = splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800442 this.baseRevisionCode = baseApk.revisionCode;
443 this.splitRevisionCodes = splitRevisionCodes;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700444 this.coreApp = baseApk.coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100445 this.debuggable = baseApk.debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100446 this.multiArch = baseApk.multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800447 this.use32bitAbi = baseApk.use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700448 this.extractNativeLibs = baseApk.extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800449 this.isolatedSplits = baseApk.isolatedSplits;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700450 }
451
452 public List<String> getAllCodePaths() {
453 ArrayList<String> paths = new ArrayList<>();
454 paths.add(baseCodePath);
455 if (!ArrayUtils.isEmpty(splitCodePaths)) {
456 Collections.addAll(paths, splitCodePaths);
457 }
458 return paths;
459 }
460 }
461
462 /**
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700463 * Lightweight parsed details about a single APK file.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800464 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700465 public static class ApkLite {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700466 public final String codePath;
Kenny Root05ca4c92011-09-15 10:36:25 -0700467 public final String packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700468 public final String splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800469 public boolean isFeatureSplit;
470 public final String configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800471 public final String usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700472 public final int versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700473 public final int versionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800474 public final int revisionCode;
Kenny Root05ca4c92011-09-15 10:36:25 -0700475 public final int installLocation;
476 public final VerifierInfo[] verifiers;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800477 public final SigningDetails signingDetails;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700478 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100479 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100480 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800481 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700482 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800483 public final boolean isolatedSplits;
Kenny Root05ca4c92011-09-15 10:36:25 -0700484
Patrick Baumann47117fc2017-12-19 10:17:21 -0800485 public ApkLite(String codePath, String packageName, String splitName,
486 boolean isFeatureSplit,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700487 String configForSplit, String usesSplitName, int versionCode, int versionCodeMajor,
488 int revisionCode, int installLocation, List<VerifierInfo> verifiers,
Patrick Baumann47117fc2017-12-19 10:17:21 -0800489 SigningDetails signingDetails, boolean coreApp,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700490 boolean debuggable, boolean multiArch, boolean use32bitAbi,
491 boolean extractNativeLibs, boolean isolatedSplits) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700492 this.codePath = codePath;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800493 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700494 this.splitName = splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800495 this.isFeatureSplit = isFeatureSplit;
496 this.configForSplit = configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800497 this.usesSplitName = usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700498 this.versionCode = versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700499 this.versionCodeMajor = versionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800500 this.revisionCode = revisionCode;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800501 this.installLocation = installLocation;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800502 this.signingDetails = signingDetails;
Kenny Root05ca4c92011-09-15 10:36:25 -0700503 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700504 this.coreApp = coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100505 this.debuggable = debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100506 this.multiArch = multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800507 this.use32bitAbi = use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700508 this.extractNativeLibs = extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800509 this.isolatedSplits = isolatedSplits;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800510 }
Dianne Hackborn3accca02013-09-20 09:32:11 -0700511
512 public long getLongVersionCode() {
513 return PackageInfo.composeLongVersionCode(versionCodeMajor, versionCode);
514 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800515 }
516
Garrett Boyer52136662017-05-23 13:47:58 -0700517 /**
518 * Cached parse state for new components.
519 *
520 * Allows reuse of the same parse argument records to avoid GC pressure. Lifetime is carefully
521 * scoped to the parsing of a single application element.
522 */
523 private static class CachedComponentArgs {
524 ParseComponentArgs mActivityArgs;
525 ParseComponentArgs mActivityAliasArgs;
526 ParseComponentArgs mServiceArgs;
527 ParseComponentArgs mProviderArgs;
528 }
529
530 /**
531 * Cached state for parsing instrumentation to avoid GC pressure.
532 *
533 * Must be manually reset to null for each new manifest.
534 */
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700535 private ParsePackageItemArgs mParseInstrumentationArgs;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 /** If set to true, we will only allow package files that exactly match
538 * the DTD. Otherwise, we try to get as much from the package as we
539 * can without failing. This should normally be set to false, to
540 * support extensions to the DTD in future versions. */
541 private static final boolean RIGID_PARSER = false;
542
543 private static final String TAG = "PackageParser";
544
Jeff Sharkey275e0852014-06-17 18:18:49 -0700545 public PackageParser() {
546 mMetrics = new DisplayMetrics();
547 mMetrics.setToDefaults();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700548 }
549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 public void setSeparateProcesses(String[] procs) {
551 mSeparateProcesses = procs;
552 }
553
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700554 /**
555 * Flag indicating this parser should only consider apps with
556 * {@code coreApp} manifest attribute to be valid apps. This is useful when
557 * creating a minimalist boot environment.
558 */
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700559 public void setOnlyCoreApps(boolean onlyCoreApps) {
560 mOnlyCoreApps = onlyCoreApps;
561 }
562
Jeff Sharkey275e0852014-06-17 18:18:49 -0700563 public void setDisplayMetrics(DisplayMetrics metrics) {
564 mMetrics = metrics;
565 }
566
Narayan Kamath988149c2016-12-01 13:32:59 +0000567 /**
568 * Sets the cache directory for this package parser.
569 */
570 public void setCacheDir(File cacheDir) {
571 mCacheDir = cacheDir;
572 }
573
Dianne Hackborncd154e92017-02-28 17:37:35 -0800574 /**
575 * Callback interface for retrieving information that may be needed while parsing
576 * a package.
577 */
578 public interface Callback {
579 boolean hasFeature(String feature);
Jaekyun Seok30dc2a02017-04-11 09:41:11 +0900580 String[] getOverlayPaths(String targetPackageName, String targetPath);
581 String[] getOverlayApks(String targetPackageName);
Dianne Hackborncd154e92017-02-28 17:37:35 -0800582 }
583
584 /**
585 * Standard implementation of {@link Callback} on top of the public {@link PackageManager}
586 * class.
587 */
588 public static final class CallbackImpl implements Callback {
589 private final PackageManager mPm;
590
591 public CallbackImpl(PackageManager pm) {
592 mPm = pm;
593 }
594
595 @Override public boolean hasFeature(String feature) {
596 return mPm.hasSystemFeature(feature);
597 }
Jaekyun Seok30dc2a02017-04-11 09:41:11 +0900598
599 @Override public String[] getOverlayPaths(String targetPackageName, String targetPath) {
600 return null;
601 }
602
603 @Override public String[] getOverlayApks(String targetPackageName) {
604 return null;
605 }
Dianne Hackborncd154e92017-02-28 17:37:35 -0800606 }
607
608 /**
609 * Set the {@link Callback} that can be used while parsing.
610 */
611 public void setCallback(Callback cb) {
612 mCallback = cb;
613 }
614
Jeff Sharkey73767b92014-07-04 20:18:13 -0700615 public static final boolean isApkFile(File file) {
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700616 return isApkPath(file.getName());
617 }
618
Adam Lesinski4e862812016-11-21 16:02:24 -0800619 public static boolean isApkPath(String path) {
Calin Juravle3fc56c32017-12-11 18:26:13 -0800620 return path.endsWith(APK_FILE_EXTENSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 }
622
623 /**
624 * Generate and return the {@link PackageInfo} for a parsed package.
625 *
626 * @param p the parsed package.
627 * @param flags indicating which optional information is included.
628 */
629 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Dianne Hackborne639da72012-02-21 15:11:13 -0800630 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svet Ganov3695b8a2015-03-24 16:30:25 -0700631 Set<String> grantedPermissions, PackageUserState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632
Amith Yamasani483f3b02012-03-13 16:08:00 -0700633 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700634 grantedPermissions, state, UserHandle.getCallingUserId());
635 }
636
Amith Yamasani655d0e22013-06-12 14:19:10 -0700637 /**
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700638 * Returns true if the package is installed and not hidden, or if the caller
639 * explicitly wanted all uninstalled and hidden packages as well.
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700640 * @param appInfo The applicationInfo of the app being checked.
Amith Yamasani655d0e22013-06-12 14:19:10 -0700641 */
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700642 private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state,
643 ApplicationInfo appInfo) {
644 // If available for the target user, or trying to match uninstalled packages and it's
645 // a system app.
646 return state.isAvailable(flags)
647 || (appInfo != null && appInfo.isSystemApp()
648 && (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0);
Amith Yamasani483f3b02012-03-13 16:08:00 -0700649 }
650
Christopher Tateba629da2013-11-13 17:42:28 -0800651 public static boolean isAvailable(PackageUserState state) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700652 return checkUseInstalledOrHidden(0, state, null);
Christopher Tateba629da2013-11-13 17:42:28 -0800653 }
654
Amith Yamasani13593602012-03-22 16:16:17 -0700655 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Amith Yamasani483f3b02012-03-13 16:08:00 -0700656 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svetoslavc6d1c342015-02-26 14:44:43 -0800657 Set<String> grantedPermissions, PackageUserState state, int userId) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700658 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700659 return null;
660 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800661 PackageInfo pi = new PackageInfo();
662 pi.packageName = p.packageName;
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700663 pi.splitNames = p.splitNames;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664 pi.versionCode = p.mVersionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700665 pi.versionCodeMajor = p.mVersionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800666 pi.baseRevisionCode = p.baseRevisionCode;
667 pi.splitRevisionCodes = p.splitRevisionCodes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800668 pi.versionName = p.mVersionName;
669 pi.sharedUserId = p.mSharedUserId;
670 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700671 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800672 pi.installLocation = p.installLocation;
Todd Kennedy7c8addf2017-06-27 14:13:55 -0700673 pi.isStub = p.isStub;
Jeff Hao272bf3a2014-10-08 13:34:43 -0700674 pi.coreApp = p.coreApp;
Amith Yamasani0d8750d2013-05-01 15:25:28 -0700675 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
676 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
677 pi.requiredForAllUsers = p.mRequiredForAllUsers;
678 }
Amith Yamasani0ac1fc92013-03-27 18:56:08 -0700679 pi.restrictedAccountType = p.mRestrictedAccountType;
Amith Yamasaniccbe3892013-04-12 17:52:42 -0700680 pi.requiredAccountType = p.mRequiredAccountType;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100681 pi.overlayTarget = p.mOverlayTarget;
Jaekyun Seok42d53f62017-04-10 13:48:58 +0900682 pi.overlayPriority = p.mOverlayPriority;
Adam Lesinskie7334972018-01-17 16:13:52 -0800683 pi.mOverlayIsStatic = p.mOverlayIsStatic;
Alan Viveretteb6a25732017-11-21 14:49:24 -0500684 pi.compileSdkVersion = p.mCompileSdkVersion;
685 pi.compileSdkVersionCodename = p.mCompileSdkVersionCodename;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700686 pi.firstInstallTime = firstInstallTime;
687 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800688 if ((flags&PackageManager.GET_GIDS) != 0) {
689 pi.gids = gids;
690 }
691 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700692 int N = p.configPreferences != null ? p.configPreferences.size() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693 if (N > 0) {
694 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700695 p.configPreferences.toArray(pi.configPreferences);
696 }
697 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
698 if (N > 0) {
699 pi.reqFeatures = new FeatureInfo[N];
700 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800701 }
Adam Lesinskid3edfde2014-08-08 17:32:44 -0700702 N = p.featureGroups != null ? p.featureGroups.size() : 0;
703 if (N > 0) {
704 pi.featureGroups = new FeatureGroupInfo[N];
705 p.featureGroups.toArray(pi.featureGroups);
706 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700708 if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
709 final int N = p.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700711 int num = 0;
712 final ActivityInfo[] res = new ActivityInfo[N];
713 for (int i = 0; i < N; i++) {
714 final Activity a = p.activities.get(i);
715 if (state.isMatch(a.info, flags)) {
716 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800717 }
718 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700719 pi.activities = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720 }
721 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700722 if ((flags & PackageManager.GET_RECEIVERS) != 0) {
723 final int N = p.receivers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800724 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700725 int num = 0;
726 final ActivityInfo[] res = new ActivityInfo[N];
727 for (int i = 0; i < N; i++) {
728 final Activity a = p.receivers.get(i);
729 if (state.isMatch(a.info, flags)) {
730 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800731 }
732 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700733 pi.receivers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 }
735 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700736 if ((flags & PackageManager.GET_SERVICES) != 0) {
737 final int N = p.services.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700739 int num = 0;
740 final ServiceInfo[] res = new ServiceInfo[N];
741 for (int i = 0; i < N; i++) {
742 final Service s = p.services.get(i);
743 if (state.isMatch(s.info, flags)) {
744 res[num++] = generateServiceInfo(s, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800745 }
746 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700747 pi.services = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748 }
749 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700750 if ((flags & PackageManager.GET_PROVIDERS) != 0) {
751 final int N = p.providers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700753 int num = 0;
754 final ProviderInfo[] res = new ProviderInfo[N];
755 for (int i = 0; i < N; i++) {
756 final Provider pr = p.providers.get(i);
757 if (state.isMatch(pr.info, flags)) {
758 res[num++] = generateProviderInfo(pr, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 }
760 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700761 pi.providers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800762 }
763 }
764 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
765 int N = p.instrumentation.size();
766 if (N > 0) {
767 pi.instrumentation = new InstrumentationInfo[N];
768 for (int i=0; i<N; i++) {
769 pi.instrumentation[i] = generateInstrumentationInfo(
770 p.instrumentation.get(i), flags);
771 }
772 }
773 }
774 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
775 int N = p.permissions.size();
776 if (N > 0) {
777 pi.permissions = new PermissionInfo[N];
778 for (int i=0; i<N; i++) {
779 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
780 }
781 }
782 N = p.requestedPermissions.size();
783 if (N > 0) {
784 pi.requestedPermissions = new String[N];
Dianne Hackborne639da72012-02-21 15:11:13 -0800785 pi.requestedPermissionsFlags = new int[N];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 for (int i=0; i<N; i++) {
Dianne Hackborne639da72012-02-21 15:11:13 -0800787 final String perm = p.requestedPermissions.get(i);
788 pi.requestedPermissions[i] = perm;
Svet Ganov3695b8a2015-03-24 16:30:25 -0700789 // The notion of required permissions is deprecated but for compatibility.
Svetoslavc6d1c342015-02-26 14:44:43 -0800790 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800791 if (grantedPermissions != null && grantedPermissions.contains(perm)) {
792 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
793 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 }
795 }
796 }
Daniel Cashman5cdda342018-01-19 07:22:52 -0800797 // deprecated method of getting signing certificates
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Daniel Cashman5cdda342018-01-19 07:22:52 -0800799 if (p.mSigningDetails.hasPastSigningCertificates()) {
800 // Package has included signing certificate rotation information. Return the oldest
801 // cert so that programmatic checks keep working even if unaware of key rotation.
802 pi.signatures = new Signature[1];
803 pi.signatures[0] = p.mSigningDetails.pastSigningCertificates[0];
804 } else if (p.mSigningDetails.hasSignatures()) {
805 // otherwise keep old behavior
Patrick Baumann47117fc2017-12-19 10:17:21 -0800806 int numberOfSigs = p.mSigningDetails.signatures.length;
807 pi.signatures = new Signature[numberOfSigs];
808 System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800809 }
810 }
Daniel Cashman5cdda342018-01-19 07:22:52 -0800811
812 // replacement for GET_SIGNATURES
813 if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
814 if (p.mSigningDetails.hasPastSigningCertificates()) {
815 // Package has included signing certificate rotation information. Convert each
816 // entry to an array
817 int numberOfSigs = p.mSigningDetails.pastSigningCertificates.length;
818 pi.signingCertificateHistory = new Signature[numberOfSigs][];
819 for (int i = 0; i < numberOfSigs; i++) {
820 pi.signingCertificateHistory[i] =
821 new Signature[] { p.mSigningDetails.pastSigningCertificates[i] };
822 }
823 } else if (p.mSigningDetails.hasSignatures()) {
824 // otherwise keep old behavior
825 int numberOfSigs = p.mSigningDetails.signatures.length;
826 pi.signingCertificateHistory = new Signature[1][numberOfSigs];
827 System.arraycopy(p.mSigningDetails.signatures, 0,
828 pi.signingCertificateHistory[0], 0, numberOfSigs);
829 }
830 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831 return pi;
832 }
833
Todd Kennedy232d29e2017-11-06 14:45:53 -0800834 public static final int PARSE_MUST_BE_APK = 1 << 0;
835 public static final int PARSE_IGNORE_PROCESSES = 1 << 1;
Todd Kennedy30a23a52018-01-04 13:27:49 -0800836 /** @deprecated forward lock no longer functional. remove. */
837 @Deprecated
Todd Kennedy232d29e2017-11-06 14:45:53 -0800838 public static final int PARSE_FORWARD_LOCK = 1 << 2;
839 public static final int PARSE_EXTERNAL_STORAGE = 1 << 3;
840 public static final int PARSE_IS_SYSTEM_DIR = 1 << 4;
841 public static final int PARSE_COLLECT_CERTIFICATES = 1 << 5;
842 public static final int PARSE_ENFORCE_CODE = 1 << 6;
843 public static final int PARSE_FORCE_SDK = 1 << 7;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800844 public static final int PARSE_CHATTY = 1 << 31;
845
846 @IntDef(flag = true, prefix = { "PARSE_" }, value = {
847 PARSE_CHATTY,
848 PARSE_COLLECT_CERTIFICATES,
849 PARSE_ENFORCE_CODE,
850 PARSE_EXTERNAL_STORAGE,
851 PARSE_FORCE_SDK,
852 PARSE_FORWARD_LOCK,
853 PARSE_IGNORE_PROCESSES,
Todd Kennedy232d29e2017-11-06 14:45:53 -0800854 PARSE_IS_SYSTEM_DIR,
855 PARSE_MUST_BE_APK,
856 })
857 @Retention(RetentionPolicy.SOURCE)
858 public @interface ParseFlags {}
Jeff Sharkey275e0852014-06-17 18:18:49 -0700859
860 private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800861
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700862 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700863 * Used to sort a set of APKs based on their split names, always placing the
864 * base APK (with {@code null} split name) first.
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700865 */
Jeff Sharkey275e0852014-06-17 18:18:49 -0700866 private static class SplitNameComparator implements Comparator<String> {
867 @Override
868 public int compare(String lhs, String rhs) {
869 if (lhs == null) {
870 return -1;
871 } else if (rhs == null) {
872 return 1;
873 } else {
874 return lhs.compareTo(rhs);
875 }
876 }
877 }
878
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700879 /**
880 * Parse only lightweight details about the package at the given location.
881 * Automatically detects if the package is a monolithic style (single APK
882 * file) or cluster style (directory of APKs).
883 * <p>
884 * This performs sanity checking on cluster style packages, such as
885 * requiring identical package name and version codes, a single base APK,
886 * and unique split names.
887 *
888 * @see PackageParser#parsePackage(File, int)
889 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700890 public static PackageLite parsePackageLite(File packageFile, int flags)
891 throws PackageParserException {
892 if (packageFile.isDirectory()) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800893 return parseClusterPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700894 } else {
Adam Lesinski4e862812016-11-21 16:02:24 -0800895 return parseMonolithicPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700896 }
897 }
898
Adam Lesinski4e862812016-11-21 16:02:24 -0800899 private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
900 throws PackageParserException {
Todd Kennedycd029da2016-07-21 07:41:09 -0700901 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Adam Lesinski4e862812016-11-21 16:02:24 -0800902 final ApkLite baseApk = parseApkLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700903 final String packagePath = packageFile.getAbsolutePath();
Todd Kennedycd029da2016-07-21 07:41:09 -0700904 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Narayan Kamath96c11c52017-08-09 13:07:21 +0100905 return new PackageLite(packagePath, baseApk, null, null, null, null, null, null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700906 }
907
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800908 static PackageLite parseClusterPackageLite(File packageDir, int flags)
Adam Lesinski4e862812016-11-21 16:02:24 -0800909 throws PackageParserException {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700910 final File[] files = packageDir.listFiles();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700911 if (ArrayUtils.isEmpty(files)) {
912 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
913 "No packages found in split");
914 }
915
Jeff Sharkey275e0852014-06-17 18:18:49 -0700916 String packageName = null;
917 int versionCode = 0;
918
Todd Kennedycd029da2016-07-21 07:41:09 -0700919 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700920 final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700921 for (File file : files) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700922 if (isApkFile(file)) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800923 final ApkLite lite = parseApkLite(file, flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -0700924
925 // Assert that all package names and version codes are
926 // consistent with the first one we encounter.
927 if (packageName == null) {
928 packageName = lite.packageName;
929 versionCode = lite.versionCode;
930 } else {
931 if (!packageName.equals(lite.packageName)) {
932 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
933 "Inconsistent package " + lite.packageName + " in " + file
934 + "; expected " + packageName);
935 }
936 if (versionCode != lite.versionCode) {
937 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
938 "Inconsistent version " + lite.versionCode + " in " + file
939 + "; expected " + versionCode);
940 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700941 }
942
Jeff Sharkey275e0852014-06-17 18:18:49 -0700943 // Assert that each split is defined only once
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700944 if (apks.put(lite.splitName, lite) != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700945 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
946 "Split name " + lite.splitName
947 + " defined more than once; most recent was " + file);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700948 }
949 }
950 }
Todd Kennedycd029da2016-07-21 07:41:09 -0700951 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700952
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700953 final ApkLite baseApk = apks.remove(null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700954 if (baseApk == null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700955 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
Jeff Sharkey73767b92014-07-04 20:18:13 -0700956 "Missing base APK in " + packageDir);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700957 }
958
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700959 // Always apply deterministic ordering based on splitName
960 final int size = apks.size();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700961
Jeff Sharkey73767b92014-07-04 20:18:13 -0700962 String[] splitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800963 boolean[] isFeatureSplits = null;
Adam Lesinski4e862812016-11-21 16:02:24 -0800964 String[] usesSplitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800965 String[] configForSplits = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700966 String[] splitCodePaths = null;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800967 int[] splitRevisionCodes = null;
Narayan Kamathf9419f02017-06-15 11:35:38 +0100968 String[] splitClassLoaderNames = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700969 if (size > 0) {
970 splitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800971 isFeatureSplits = new boolean[size];
Adam Lesinski4e862812016-11-21 16:02:24 -0800972 usesSplitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800973 configForSplits = new String[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700974 splitCodePaths = new String[size];
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800975 splitRevisionCodes = new int[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700976
977 splitNames = apks.keySet().toArray(splitNames);
978 Arrays.sort(splitNames, sSplitNameComparator);
979
980 for (int i = 0; i < size; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800981 final ApkLite apk = apks.get(splitNames[i]);
982 usesSplitNames[i] = apk.usesSplitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800983 isFeatureSplits[i] = apk.isFeatureSplit;
984 configForSplits[i] = apk.configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800985 splitCodePaths[i] = apk.codePath;
986 splitRevisionCodes[i] = apk.revisionCode;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700987 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700988 }
989
Jeff Sharkey73767b92014-07-04 20:18:13 -0700990 final String codePath = packageDir.getAbsolutePath();
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800991 return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100992 configForSplits, splitCodePaths, splitRevisionCodes);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700993 }
994
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700995 /**
996 * Parse the package at the given location. Automatically detects if the
997 * package is a monolithic style (single APK file) or cluster style
998 * (directory of APKs).
999 * <p>
1000 * This performs sanity checking on cluster style packages, such as
1001 * requiring identical package name and version codes, a single base APK,
1002 * and unique split names.
1003 * <p>
1004 * Note that this <em>does not</em> perform signature verification; that
1005 * must be done separately in {@link #collectCertificates(Package, int)}.
1006 *
Narayan Kamath988149c2016-12-01 13:32:59 +00001007 * If {@code useCaches} is true, the package parser might return a cached
1008 * result from a previous parse of the same {@code packageFile} with the same
1009 * {@code flags}. Note that this method does not check whether {@code packageFile}
1010 * has changed since the last parse, it's up to callers to do so.
1011 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001012 * @see #parsePackageLite(File, int)
1013 */
Narayan Kamath988149c2016-12-01 13:32:59 +00001014 public Package parsePackage(File packageFile, int flags, boolean useCaches)
1015 throws PackageParserException {
1016 Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
1017 if (parsed != null) {
1018 return parsed;
1019 }
1020
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001021 long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Jeff Sharkey73767b92014-07-04 20:18:13 -07001022 if (packageFile.isDirectory()) {
Narayan Kamath988149c2016-12-01 13:32:59 +00001023 parsed = parseClusterPackage(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001024 } else {
Narayan Kamath988149c2016-12-01 13:32:59 +00001025 parsed = parseMonolithicPackage(packageFile, flags);
1026 }
1027
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001028 long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Narayan Kamath988149c2016-12-01 13:32:59 +00001029 cacheResult(packageFile, flags, parsed);
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001030 if (LOG_PARSE_TIMINGS) {
1031 parseTime = cacheTime - parseTime;
1032 cacheTime = SystemClock.uptimeMillis() - cacheTime;
1033 if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) {
1034 Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime
1035 + "ms, update_cache=" + cacheTime + " ms");
1036 }
1037 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001038 return parsed;
1039 }
1040
1041 /**
1042 * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}.
1043 */
1044 public Package parsePackage(File packageFile, int flags) throws PackageParserException {
1045 return parsePackage(packageFile, flags, false /* useCaches */);
1046 }
1047
1048 /**
1049 * Returns the cache key for a specificied {@code packageFile} and {@code flags}.
1050 */
1051 private String getCacheKey(File packageFile, int flags) {
1052 StringBuilder sb = new StringBuilder(packageFile.getName());
1053 sb.append('-');
1054 sb.append(flags);
1055
1056 return sb.toString();
1057 }
1058
1059 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001060 protected Package fromCacheEntry(byte[] bytes) {
1061 return fromCacheEntryStatic(bytes);
1062 }
1063
1064 /** static version of {@link #fromCacheEntry} for unit tests. */
1065 @VisibleForTesting
1066 public static Package fromCacheEntryStatic(byte[] bytes) {
1067 final Parcel p = Parcel.obtain();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001068 p.unmarshall(bytes, 0, bytes.length);
1069 p.setDataPosition(0);
1070
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001071 final ReadHelper helper = new ReadHelper(p);
1072 helper.startAndInstall();
1073
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001074 PackageParser.Package pkg = new PackageParser.Package(p);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001075
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001076 p.recycle();
1077
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001078 sCachedPackageReadCount.incrementAndGet();
1079
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001080 return pkg;
Narayan Kamath988149c2016-12-01 13:32:59 +00001081 }
1082
1083 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001084 protected byte[] toCacheEntry(Package pkg) {
1085 return toCacheEntryStatic(pkg);
1086
1087 }
1088
1089 /** static version of {@link #toCacheEntry} for unit tests. */
1090 @VisibleForTesting
1091 public static byte[] toCacheEntryStatic(Package pkg) {
1092 final Parcel p = Parcel.obtain();
1093 final WriteHelper helper = new WriteHelper(p);
1094
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001095 pkg.writeToParcel(p, 0 /* flags */);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001096
1097 helper.finishAndUninstall();
1098
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001099 byte[] serialized = p.marshall();
1100 p.recycle();
1101
1102 return serialized;
Narayan Kamath988149c2016-12-01 13:32:59 +00001103 }
1104
1105 /**
1106 * Given a {@code packageFile} and a {@code cacheFile} returns whether the
1107 * cache file is up to date based on the mod-time of both files.
1108 */
1109 private static boolean isCacheUpToDate(File packageFile, File cacheFile) {
1110 try {
1111 // NOTE: We don't use the File.lastModified API because it has the very
1112 // non-ideal failure mode of returning 0 with no excepions thrown.
1113 // The nio2 Files API is a little better but is considerably more expensive.
1114 final StructStat pkg = android.system.Os.stat(packageFile.getAbsolutePath());
1115 final StructStat cache = android.system.Os.stat(cacheFile.getAbsolutePath());
1116 return pkg.st_mtime < cache.st_mtime;
1117 } catch (ErrnoException ee) {
1118 // The most common reason why stat fails is that a given cache file doesn't
1119 // exist. We ignore that here. It's easy to reason that it's safe to say the
1120 // cache isn't up to date if we see any sort of exception here.
1121 //
1122 // (1) Exception while stating the package file : This should never happen,
1123 // and if it does, we do a full package parse (which is likely to throw the
1124 // same exception).
1125 // (2) Exception while stating the cache file : If the file doesn't exist, the
1126 // cache is obviously out of date. If the file *does* exist, we can't read it.
1127 // We will attempt to delete and recreate it after parsing the package.
1128 if (ee.errno != OsConstants.ENOENT) {
1129 Slog.w("Error while stating package cache : ", ee);
1130 }
1131
1132 return false;
1133 }
1134 }
1135
1136 /**
1137 * Returns the cached parse result for {@code packageFile} for parse flags {@code flags},
1138 * or {@code null} if no cached result exists.
1139 */
1140 private Package getCachedResult(File packageFile, int flags) {
1141 if (mCacheDir == null) {
1142 return null;
1143 }
1144
1145 final String cacheKey = getCacheKey(packageFile, flags);
1146 final File cacheFile = new File(mCacheDir, cacheKey);
1147
Narayan Kamath988149c2016-12-01 13:32:59 +00001148 try {
Makoto Onuki48e93162017-08-18 11:00:19 -07001149 // If the cache is not up to date, return null.
1150 if (!isCacheUpToDate(packageFile, cacheFile)) {
1151 return null;
1152 }
1153
Narayan Kamath988149c2016-12-01 13:32:59 +00001154 final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001155 Package p = fromCacheEntry(bytes);
1156 if (mCallback != null) {
1157 String[] overlayApks = mCallback.getOverlayApks(p.packageName);
1158 if (overlayApks != null && overlayApks.length > 0) {
1159 for (String overlayApk : overlayApks) {
1160 // If a static RRO is updated, return null.
1161 if (!isCacheUpToDate(new File(overlayApk), cacheFile)) {
1162 return null;
1163 }
1164 }
1165 }
1166 }
1167 return p;
Makoto Onuki48e93162017-08-18 11:00:19 -07001168 } catch (Throwable e) {
Narayan Kamath21a28382017-01-13 10:34:29 +00001169 Slog.w(TAG, "Error reading package cache: ", e);
Narayan Kamath988149c2016-12-01 13:32:59 +00001170
1171 // If something went wrong while reading the cache entry, delete the cache file
1172 // so that we regenerate it the next time.
1173 cacheFile.delete();
1174 return null;
1175 }
1176 }
1177
1178 /**
1179 * Caches the parse result for {@code packageFile} with flags {@code flags}.
1180 */
1181 private void cacheResult(File packageFile, int flags, Package parsed) {
1182 if (mCacheDir == null) {
1183 return;
1184 }
1185
Makoto Onuki48e93162017-08-18 11:00:19 -07001186 try {
1187 final String cacheKey = getCacheKey(packageFile, flags);
1188 final File cacheFile = new File(mCacheDir, cacheKey);
Narayan Kamath988149c2016-12-01 13:32:59 +00001189
Makoto Onuki48e93162017-08-18 11:00:19 -07001190 if (cacheFile.exists()) {
1191 if (!cacheFile.delete()) {
1192 Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
1193 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001194 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001195
Makoto Onuki48e93162017-08-18 11:00:19 -07001196 final byte[] cacheEntry = toCacheEntry(parsed);
Narayan Kamath988149c2016-12-01 13:32:59 +00001197
Makoto Onuki48e93162017-08-18 11:00:19 -07001198 if (cacheEntry == null) {
1199 return;
1200 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001201
Makoto Onuki48e93162017-08-18 11:00:19 -07001202 try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
1203 fos.write(cacheEntry);
1204 } catch (IOException ioe) {
1205 Slog.w(TAG, "Error writing cache entry.", ioe);
1206 cacheFile.delete();
1207 }
1208 } catch (Throwable e) {
1209 Slog.w(TAG, "Error saving package cache.", e);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001210 }
1211 }
1212
1213 /**
1214 * Parse all APKs contained in the given directory, treating them as a
1215 * single package. This also performs sanity checking, such as requiring
1216 * identical package name and version codes, a single base APK, and unique
1217 * split names.
1218 * <p>
1219 * Note that this <em>does not</em> perform signature verification; that
1220 * must be done separately in {@link #collectCertificates(Package, int)}.
1221 */
1222 private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
Adam Lesinski4e862812016-11-21 16:02:24 -08001223 final PackageLite lite = parseClusterPackageLite(packageDir, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001224 if (mOnlyCoreApps && !lite.coreApp) {
1225 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1226 "Not a coreApp: " + packageDir);
1227 }
1228
Adam Lesinski4e862812016-11-21 16:02:24 -08001229 // Build the split dependency tree.
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001230 SparseArray<int[]> splitDependencies = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001231 final SplitAssetLoader assetLoader;
1232 if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) {
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001233 try {
1234 splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite);
1235 assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags);
1236 } catch (SplitAssetDependencyLoader.IllegalDependencyException e) {
1237 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage());
1238 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001239 } else {
1240 assetLoader = new DefaultSplitAssetLoader(lite, flags);
1241 }
1242
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001243 try {
Adam Lesinski4e862812016-11-21 16:02:24 -08001244 final AssetManager assets = assetLoader.getBaseAssetManager();
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001245 final File baseApk = new File(lite.baseCodePath);
1246 final Package pkg = parseBaseApk(baseApk, assets, flags);
1247 if (pkg == null) {
1248 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1249 "Failed to parse base APK: " + baseApk);
1250 }
1251
1252 if (!ArrayUtils.isEmpty(lite.splitNames)) {
1253 final int num = lite.splitNames.length;
1254 pkg.splitNames = lite.splitNames;
1255 pkg.splitCodePaths = lite.splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001256 pkg.splitRevisionCodes = lite.splitRevisionCodes;
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001257 pkg.splitFlags = new int[num];
Alex Klyubinb9f8a522015-02-03 11:12:59 -08001258 pkg.splitPrivateFlags = new int[num];
Adam Lesinski4e862812016-11-21 16:02:24 -08001259 pkg.applicationInfo.splitNames = pkg.splitNames;
1260 pkg.applicationInfo.splitDependencies = splitDependencies;
Narayan Kamath96c11c52017-08-09 13:07:21 +01001261 pkg.applicationInfo.splitClassLoaderNames = new String[num];
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001262
1263 for (int i = 0; i < num; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -08001264 final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
1265 parseSplitApk(pkg, i, splitAssets, flags);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001266 }
1267 }
1268
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001269 pkg.setCodePath(packageDir.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001270 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001271 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001272 } catch (IOException e) {
1273 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1274 "Failed to get path: " + lite.baseCodePath, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001275 } finally {
Adam Lesinski4e862812016-11-21 16:02:24 -08001276 IoUtils.closeQuietly(assetLoader);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001278 }
1279
Jeff Sharkey275e0852014-06-17 18:18:49 -07001280 /**
1281 * Parse the given APK file, treating it as as a single monolithic package.
1282 * <p>
1283 * Note that this <em>does not</em> perform signature verification; that
1284 * must be done separately in {@link #collectCertificates(Package, int)}.
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001285 *
1286 * @deprecated external callers should move to
1287 * {@link #parsePackage(File, int)}. Eventually this method will
1288 * be marked private.
Jeff Sharkey275e0852014-06-17 18:18:49 -07001289 */
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001290 @Deprecated
Jeff Sharkey275e0852014-06-17 18:18:49 -07001291 public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
Fyodor Kupolov965fa692016-10-28 18:20:25 -07001292 final AssetManager assets = newConfiguredAssetManager();
Adam Lesinski4e862812016-11-21 16:02:24 -08001293 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001294 if (mOnlyCoreApps) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001295 if (!lite.coreApp) {
1296 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1297 "Not a coreApp: " + apkFile);
1298 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001299 }
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07001300
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001301 try {
1302 final Package pkg = parseBaseApk(apkFile, assets, flags);
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001303 pkg.setCodePath(apkFile.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001304 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001305 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001306 } catch (IOException e) {
1307 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1308 "Failed to get path: " + apkFile, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001309 } finally {
1310 IoUtils.closeQuietly(assets);
1311 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001312 }
1313
Artem Iglikov16b3dff2018-01-25 13:59:13 +00001314 private static int loadApkIntoAssetManager(AssetManager assets, String apkPath, int flags)
1315 throws PackageParserException {
1316 if ((flags & PARSE_MUST_BE_APK) != 0 && !isApkPath(apkPath)) {
1317 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1318 "Invalid package file: " + apkPath);
1319 }
1320
1321 // The AssetManager guarantees uniqueness for asset paths, so if this asset path
1322 // already exists in the AssetManager, addAssetPath will only return the cookie
1323 // assigned to it.
1324 int cookie = assets.addAssetPath(apkPath);
1325 if (cookie == 0) {
1326 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1327 "Failed adding asset path: " + apkPath);
1328 }
1329 return cookie;
1330 }
1331
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001332 private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
1333 throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001334 final String apkPath = apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001335
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07001336 String volumeUuid = null;
1337 if (apkPath.startsWith(MNT_EXPAND)) {
1338 final int end = apkPath.indexOf('/', MNT_EXPAND.length());
1339 volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
1340 }
1341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342 mParseError = PackageManager.INSTALL_SUCCEEDED;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001343 mArchiveSourcePath = apkFile.getAbsolutePath();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001344
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001345 if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001346
Artem Iglikov16b3dff2018-01-25 13:59:13 +00001347 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
1348
1349 Resources res = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001350 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 try {
Artem Iglikov16b3dff2018-01-25 13:59:13 +00001352 res = new Resources(assets, mMetrics, null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001353 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
1354
1355 final String[] outError = new String[1];
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001356 final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001357 if (pkg == null) {
1358 throw new PackageParserException(mParseError,
1359 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001360 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001361
Svet Ganov354cd3c2015-12-17 11:35:04 -08001362 pkg.setVolumeUuid(volumeUuid);
1363 pkg.setApplicationVolumeUuid(volumeUuid);
1364 pkg.setBaseCodePath(apkPath);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001365 pkg.setSigningDetails(SigningDetails.UNKNOWN);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001366
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001367 return pkg;
1368
1369 } catch (PackageParserException e) {
1370 throw e;
1371 } catch (Exception e) {
1372 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001373 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001374 } finally {
1375 IoUtils.closeQuietly(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377 }
1378
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001379 private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001380 throws PackageParserException {
1381 final String apkPath = pkg.splitCodePaths[splitIndex];
Jeff Sharkey275e0852014-06-17 18:18:49 -07001382
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001383 mParseError = PackageManager.INSTALL_SUCCEEDED;
1384 mArchiveSourcePath = apkPath;
1385
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001386 if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
1387
Artem Iglikov16b3dff2018-01-25 13:59:13 +00001388 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
1389
Adam Lesinski4e862812016-11-21 16:02:24 -08001390 final Resources res;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001391 XmlResourceParser parser = null;
1392 try {
Adam Lesinskie70b57a2017-12-01 18:22:37 -08001393 res = new Resources(assets, mMetrics, null);
Artem Iglikov16b3dff2018-01-25 13:59:13 +00001394 assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1395 Build.VERSION.RESOURCES_SDK_INT);
1396 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001397
1398 final String[] outError = new String[1];
1399 pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
1400 if (pkg == null) {
1401 throw new PackageParserException(mParseError,
1402 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
1403 }
1404
1405 } catch (PackageParserException e) {
1406 throw e;
1407 } catch (Exception e) {
1408 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001409 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001410 } finally {
1411 IoUtils.closeQuietly(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001412 }
1413 }
1414
1415 /**
1416 * Parse the manifest of a <em>split APK</em>.
1417 * <p>
1418 * Note that split APKs have many more restrictions on what they're capable
1419 * of doing, so many valid features of a base APK have been carefully
1420 * omitted here.
1421 */
1422 private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001423 int splitIndex, String[] outError) throws XmlPullParserException, IOException,
1424 PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001425 AttributeSet attrs = parser;
1426
Jeff Sharkey78a13012014-07-15 20:18:34 -07001427 // We parsed manifest tag earlier; just skip past it
Svet Ganov354cd3c2015-12-17 11:35:04 -08001428 parsePackageSplitNames(parser, attrs);
Jeff Sharkey78a13012014-07-15 20:18:34 -07001429
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001430 mParseInstrumentationArgs = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001431
1432 int type;
1433
1434 boolean foundApp = false;
1435
1436 int outerDepth = parser.getDepth();
1437 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1438 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1439 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1440 continue;
1441 }
1442
1443 String tagName = parser.getName();
Adam Lesinski4e862812016-11-21 16:02:24 -08001444 if (tagName.equals(TAG_APPLICATION)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001445 if (foundApp) {
1446 if (RIGID_PARSER) {
1447 outError[0] = "<manifest> has more than one <application>";
1448 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1449 return null;
1450 } else {
1451 Slog.w(TAG, "<manifest> has more than one <application>");
1452 XmlUtils.skipCurrentTag(parser);
1453 continue;
1454 }
1455 }
1456
1457 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001458 if (!parseSplitApplication(pkg, res, parser, flags, splitIndex, outError)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001459 return null;
1460 }
1461
1462 } else if (RIGID_PARSER) {
1463 outError[0] = "Bad element under <manifest>: "
1464 + parser.getName();
1465 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1466 return null;
1467
1468 } else {
1469 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1470 + " at " + mArchiveSourcePath + " "
1471 + parser.getPositionDescription());
1472 XmlUtils.skipCurrentTag(parser);
1473 continue;
1474 }
1475 }
1476
1477 if (!foundApp) {
1478 outError[0] = "<manifest> does not contain an <application>";
1479 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1480 }
1481
1482 return pkg;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001483 }
1484
Patrick Baumann47117fc2017-12-19 10:17:21 -08001485 /** Parses the public keys from the set of signatures. */
1486 public static ArraySet<PublicKey> toSigningKeys(Signature[] signatures)
1487 throws CertificateException {
1488 ArraySet<PublicKey> keys = new ArraySet<>(signatures.length);
1489 for (int i = 0; i < signatures.length; i++) {
1490 keys.add(signatures[i].getPublicKey());
Todd Kennedy66c55532016-02-26 16:22:11 -08001491 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001492 return keys;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001493 }
1494
1495 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -07001496 * Collect certificates from all the APKs described in the given package,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001497 * populating {@link Package#mSigningDetails}. Also asserts that all APK
Jeff Sharkey275e0852014-06-17 18:18:49 -07001498 * contents are signed correctly and consistently.
1499 */
Victor Hsieh5f761242018-01-20 10:30:12 -08001500 public static void collectCertificates(Package pkg, boolean skipVerify)
Todd Kennedy66c55532016-02-26 16:22:11 -08001501 throws PackageParserException {
Victor Hsieh5f761242018-01-20 10:30:12 -08001502 collectCertificatesInternal(pkg, skipVerify);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001503 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1504 for (int i = 0; i < childCount; i++) {
1505 Package childPkg = pkg.childPackages.get(i);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001506 childPkg.mSigningDetails = pkg.mSigningDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001507 }
1508 }
1509
Victor Hsieh5f761242018-01-20 10:30:12 -08001510 private static void collectCertificatesInternal(Package pkg, boolean skipVerify)
Todd Kennedy66c55532016-02-26 16:22:11 -08001511 throws PackageParserException {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001512 pkg.mSigningDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001513
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001514 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1515 try {
Victor Hsieh5f761242018-01-20 10:30:12 -08001516 collectCertificates(pkg, new File(pkg.baseCodePath), skipVerify);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001517
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001518 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
1519 for (int i = 0; i < pkg.splitCodePaths.length; i++) {
Victor Hsieh5f761242018-01-20 10:30:12 -08001520 collectCertificates(pkg, new File(pkg.splitCodePaths[i]), skipVerify);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001521 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001522 }
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001523 } finally {
1524 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001525 }
1526 }
1527
Victor Hsieh5f761242018-01-20 10:30:12 -08001528 private static void collectCertificates(Package pkg, File apkFile, boolean skipVerify)
Jeff Sharkey275e0852014-06-17 18:18:49 -07001529 throws PackageParserException {
1530 final String apkPath = apkFile.getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531
Patrick Baumann47117fc2017-12-19 10:17:21 -08001532 int minSignatureScheme = SigningDetails.SignatureSchemeVersion.JAR;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001533 if (pkg.applicationInfo.isStaticSharedLibrary()) {
Dan Cashmane92f8422017-12-08 14:02:51 -08001534 // must use v2 signing scheme
Patrick Baumann47117fc2017-12-19 10:17:21 -08001535 minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2;
Dan Cashmane92f8422017-12-08 14:02:51 -08001536 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001537 SigningDetails verified;
Victor Hsieh5f761242018-01-20 10:30:12 -08001538 if (skipVerify) {
Dan Cashman636ea5e2017-12-18 10:38:20 -08001539 // systemDir APKs are already trusted, save time by not verifying
1540 verified = ApkSignatureVerifier.plsCertsNoVerifyOnlyCerts(
1541 apkPath, minSignatureScheme);
1542 } else {
1543 verified = ApkSignatureVerifier.verify(apkPath, minSignatureScheme);
1544 }
Dan Cashman636ea5e2017-12-18 10:38:20 -08001545
1546 // Verify that entries are signed consistently with the first pkg
1547 // we encountered. Note that for splits, certificates may have
1548 // already been populated during an earlier parse of a base APK.
Patrick Baumann47117fc2017-12-19 10:17:21 -08001549 if (pkg.mSigningDetails == SigningDetails.UNKNOWN) {
1550 pkg.mSigningDetails = verified;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001551 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001552 if (!Signature.areExactMatch(pkg.mSigningDetails.signatures, verified.signatures)) {
Patrick Baumann9ff55742017-12-14 10:50:18 -08001553 throw new PackageParserException(
1554 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
1555 apkPath + " has mismatched certificates");
1556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001557 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 }
1559
Fyodor Kupolov965fa692016-10-28 18:20:25 -07001560 private static AssetManager newConfiguredAssetManager() {
1561 AssetManager assetManager = new AssetManager();
Romain Guy408afbf2017-01-25 10:23:03 -08001562 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 -07001563 Build.VERSION.RESOURCES_SDK_INT);
1564 return assetManager;
1565 }
1566
Jeff Sharkey275e0852014-06-17 18:18:49 -07001567 /**
1568 * Utility method that retrieves lightweight details about a single APK
1569 * file, including package name, split name, and install location.
1570 *
1571 * @param apkFile path to a single APK
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001572 * @param flags optional parse flags, such as
1573 * {@link #PARSE_COLLECT_CERTIFICATES}
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001574 */
Jeff Sharkey275e0852014-06-17 18:18:49 -07001575 public static ApkLite parseApkLite(File apkFile, int flags)
1576 throws PackageParserException {
Dianne Hackbornca3872c2017-10-30 14:19:32 -07001577 return parseApkLiteInner(apkFile, null, null, flags);
1578 }
1579
1580 /**
1581 * Utility method that retrieves lightweight details about a single APK
1582 * file, including package name, split name, and install location.
1583 *
1584 * @param fd already open file descriptor of an apk file
1585 * @param debugPathName arbitrary text name for this file, for debug output
1586 * @param flags optional parse flags, such as
1587 * {@link #PARSE_COLLECT_CERTIFICATES}
1588 */
1589 public static ApkLite parseApkLite(FileDescriptor fd, String debugPathName, int flags)
1590 throws PackageParserException {
1591 return parseApkLiteInner(null, fd, debugPathName, flags);
1592 }
1593
1594 private static ApkLite parseApkLiteInner(File apkFile, FileDescriptor fd, String debugPathName,
1595 int flags) throws PackageParserException {
1596 final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001597
Artem Iglikov16b3dff2018-01-25 13:59:13 +00001598 ApkAssets apkAssets = null;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001599 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600 try {
Adam Lesinskidcb3c652017-01-23 12:58:11 -08001601 try {
1602 apkAssets = fd != null
1603 ? ApkAssets.loadFromFd(fd, debugPathName, false, false)
1604 : ApkAssets.loadFromPath(apkPath);
1605 } catch (IOException e) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001606 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1607 "Failed to parse " + apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001608 }
1609
Adam Lesinskidcb3c652017-01-23 12:58:11 -08001610 parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME);
Kenny Root05ca4c92011-09-15 10:36:25 -07001611
Patrick Baumann47117fc2017-12-19 10:17:21 -08001612 final SigningDetails signingDetails;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001613 if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
1614 // TODO: factor signature related items out of Package object
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001615 final Package tempPkg = new Package((String) null);
Victor Hsieh5f761242018-01-20 10:30:12 -08001616 final boolean skipVerify = (flags & PARSE_IS_SYSTEM_DIR) != 0;
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001617 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1618 try {
Victor Hsieh5f761242018-01-20 10:30:12 -08001619 collectCertificates(tempPkg, apkFile, skipVerify);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001620 } finally {
1621 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1622 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001623 signingDetails = tempPkg.mSigningDetails;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001624 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001625 signingDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001626 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001627
Jeff Sharkey275e0852014-06-17 18:18:49 -07001628 final AttributeSet attrs = parser;
Patrick Baumann47117fc2017-12-19 10:17:21 -08001629 return parseApkLite(apkPath, parser, attrs, signingDetails);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001630
1631 } catch (XmlPullParserException | IOException | RuntimeException e) {
Dianne Hackborn34041732017-01-31 15:27:13 -08001632 Slog.w(TAG, "Failed to parse " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001633 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1634 "Failed to parse " + apkPath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 } finally {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001636 IoUtils.closeQuietly(parser);
Artem Iglikov16b3dff2018-01-25 13:59:13 +00001637 IoUtils.closeQuietly(apkAssets);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001639 }
1640
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001641 private static String validateName(String name, boolean requireSeparator,
1642 boolean requireFilename) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 final int N = name.length();
1644 boolean hasSep = false;
1645 boolean front = true;
1646 for (int i=0; i<N; i++) {
1647 final char c = name.charAt(i);
1648 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1649 front = false;
1650 continue;
1651 }
1652 if (!front) {
1653 if ((c >= '0' && c <= '9') || c == '_') {
1654 continue;
1655 }
1656 }
1657 if (c == '.') {
1658 hasSep = true;
1659 front = true;
1660 continue;
1661 }
1662 return "bad character '" + c + "'";
1663 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001664 if (requireFilename && !FileUtils.isValidExtFilename(name)) {
1665 return "Invalid filename";
1666 }
1667 return hasSep || !requireSeparator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 ? null : "must have at least one '.' separator";
1669 }
1670
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001671 private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
Svet Ganov354cd3c2015-12-17 11:35:04 -08001672 AttributeSet attrs) throws IOException, XmlPullParserException,
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001673 PackageParserException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001674
1675 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001676 while ((type = parser.next()) != XmlPullParser.START_TAG
1677 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001678 }
1679
Kenny Rootd2d29252011-08-08 11:27:57 -07001680 if (type != XmlPullParser.START_TAG) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001681 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1682 "No start tag found");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001684 if (!parser.getName().equals(TAG_MANIFEST)) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001685 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1686 "No <manifest> tag");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 }
1688
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001689 final String packageName = attrs.getAttributeValue(null, "package");
1690 if (!"android".equals(packageName)) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001691 final String error = validateName(packageName, true, true);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001692 if (error != null) {
1693 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1694 "Invalid manifest package: " + error);
1695 }
1696 }
1697
Jeff Sharkey275e0852014-06-17 18:18:49 -07001698 String splitName = attrs.getAttributeValue(null, "split");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001699 if (splitName != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001700 if (splitName.length() == 0) {
1701 splitName = null;
1702 } else {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001703 final String error = validateName(splitName, false, false);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001704 if (error != null) {
1705 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1706 "Invalid manifest split: " + error);
1707 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001708 }
1709 }
1710
1711 return Pair.create(packageName.intern(),
1712 (splitName != null) ? splitName.intern() : splitName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 }
1714
Adam Lesinski4e862812016-11-21 16:02:24 -08001715 private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001716 SigningDetails signingDetails)
Adam Lesinski4e862812016-11-21 16:02:24 -08001717 throws IOException, XmlPullParserException, PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001718 final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001719
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001720 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001721 int versionCode = 0;
Dianne Hackborn3accca02013-09-20 09:32:11 -07001722 int versionCodeMajor = 0;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001723 int revisionCode = 0;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001724 boolean coreApp = false;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001725 boolean debuggable = false;
Narayan Kamathff110bd2014-07-04 18:30:45 +01001726 boolean multiArch = false;
Selim Gurun2d291d82016-02-05 17:50:53 -08001727 boolean use32bitAbi = false;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001728 boolean extractNativeLibs = true;
Adam Lesinski4e862812016-11-21 16:02:24 -08001729 boolean isolatedSplits = false;
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001730 boolean isFeatureSplit = false;
1731 String configForSplit = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001732 String usesSplitName = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001733
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001734 for (int i = 0; i < attrs.getAttributeCount(); i++) {
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001735 final String attr = attrs.getAttributeName(i);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001736 if (attr.equals("installLocation")) {
1737 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001738 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001739 } else if (attr.equals("versionCode")) {
1740 versionCode = attrs.getAttributeIntValue(i, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001741 } else if (attr.equals("versionCodeMajor")) {
1742 versionCodeMajor = attrs.getAttributeIntValue(i, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001743 } else if (attr.equals("revisionCode")) {
1744 revisionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001745 } else if (attr.equals("coreApp")) {
1746 coreApp = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski4e862812016-11-21 16:02:24 -08001747 } else if (attr.equals("isolatedSplits")) {
1748 isolatedSplits = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001749 } else if (attr.equals("configForSplit")) {
1750 configForSplit = attrs.getAttributeValue(i);
1751 } else if (attr.equals("isFeatureSplit")) {
1752 isFeatureSplit = attrs.getAttributeBooleanValue(i, false);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001753 }
1754 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001755
1756 // Only search the tree when the tag is directly below <manifest>
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001757 int type;
Kenny Root05ca4c92011-09-15 10:36:25 -07001758 final int searchDepth = parser.getDepth() + 1;
1759
1760 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
1761 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1762 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
1763 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1764 continue;
1765 }
1766
Adam Lesinski4e862812016-11-21 16:02:24 -08001767 if (parser.getDepth() != searchDepth) {
1768 continue;
1769 }
1770
1771 if (TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
1772 final VerifierInfo verifier = parseVerifier(attrs);
Kenny Root05ca4c92011-09-15 10:36:25 -07001773 if (verifier != null) {
1774 verifiers.add(verifier);
1775 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001776 } else if (TAG_APPLICATION.equals(parser.getName())) {
Narayan Kamatha8755a82014-07-15 12:26:35 +01001777 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1778 final String attr = attrs.getAttributeName(i);
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001779 if ("debuggable".equals(attr)) {
1780 debuggable = attrs.getAttributeBooleanValue(i, false);
1781 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001782 if ("multiArch".equals(attr)) {
1783 multiArch = attrs.getAttributeBooleanValue(i, false);
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001784 }
Selim Gurun2d291d82016-02-05 17:50:53 -08001785 if ("use32bitAbi".equals(attr)) {
1786 use32bitAbi = attrs.getAttributeBooleanValue(i, false);
Tao Baic9a02372016-01-12 15:02:24 -08001787 }
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001788 if ("extractNativeLibs".equals(attr)) {
1789 extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
Narayan Kamatha8755a82014-07-15 12:26:35 +01001790 }
1791 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001792 } else if (TAG_USES_SPLIT.equals(parser.getName())) {
1793 if (usesSplitName != null) {
1794 Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
1795 continue;
1796 }
1797
1798 usesSplitName = attrs.getAttributeValue(ANDROID_RESOURCES, "name");
1799 if (usesSplitName == null) {
1800 throw new PackageParserException(
1801 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1802 "<uses-split> tag requires 'android:name' attribute");
1803 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001804 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001805 }
1806
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001807 return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
Dianne Hackborn3accca02013-09-20 09:32:11 -07001808 configForSplit, usesSplitName, versionCode, versionCodeMajor, revisionCode,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001809 installLocation, verifiers, signingDetails, coreApp, debuggable,
Dianne Hackborn3accca02013-09-20 09:32:11 -07001810 multiArch, use32bitAbi, extractNativeLibs, isolatedSplits);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 }
1812
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001813 /**
Svet Ganov354cd3c2015-12-17 11:35:04 -08001814 * Parses a child package and adds it to the parent if successful. If you add
1815 * new tags that need to be supported by child packages make sure to add them
1816 * to {@link #CHILD_PACKAGE_TAGS}.
1817 *
1818 * @param parentPkg The parent that contains the child
1819 * @param res Resources against which to resolve values
1820 * @param parser Parser of the manifest
1821 * @param flags Flags about how to parse
1822 * @param outError Human readable error if parsing fails
1823 * @return True of parsing succeeded.
1824 *
1825 * @throws XmlPullParserException
1826 * @throws IOException
1827 */
1828 private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser,
1829 int flags, String[] outError) throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001830 // Make sure we have a valid child package name
1831 String childPackageName = parser.getAttributeValue(null, "package");
1832 if (validateName(childPackageName, true, false) != null) {
1833 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1834 return false;
1835 }
1836
1837 // Child packages must be unique
1838 if (childPackageName.equals(parentPkg.packageName)) {
1839 String message = "Child package name cannot be equal to parent package name: "
1840 + parentPkg.packageName;
1841 Slog.w(TAG, message);
1842 outError[0] = message;
1843 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1844 return false;
1845 }
1846
1847 // Child packages must be unique
1848 if (parentPkg.hasChildPackage(childPackageName)) {
1849 String message = "Duplicate child package:" + childPackageName;
1850 Slog.w(TAG, message);
1851 outError[0] = message;
1852 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1853 return false;
1854 }
1855
1856 // Go ahead and parse the child
1857 Package childPkg = new Package(childPackageName);
1858
1859 // Child package inherits parent version code/name/target SDK
1860 childPkg.mVersionCode = parentPkg.mVersionCode;
1861 childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
1862 childPkg.mVersionName = parentPkg.mVersionName;
1863 childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
Todd Kennedy89d60182016-03-11 11:18:32 -08001864 childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001865
1866 childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
1867 if (childPkg == null) {
1868 // If we got null then error was set during child parsing
1869 return false;
1870 }
1871
1872 // Set the parent-child relation
1873 if (parentPkg.childPackages == null) {
1874 parentPkg.childPackages = new ArrayList<>();
1875 }
1876 parentPkg.childPackages.add(childPkg);
1877 childPkg.parentPackage = parentPkg;
1878
1879 return true;
1880 }
1881
1882 /**
1883 * Parse the manifest of a <em>base APK</em>. When adding new features you
1884 * need to consider whether they should be supported by split APKs and child
1885 * packages.
1886 *
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001887 * @param apkPath The package apk file path
Svet Ganov354cd3c2015-12-17 11:35:04 -08001888 * @param res The resources from which to resolve values
1889 * @param parser The manifest parser
1890 * @param flags Flags how to parse
1891 * @param outError Human readable error message
1892 * @return Parsed package or null on error.
1893 *
1894 * @throws XmlPullParserException
1895 * @throws IOException
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001896 */
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001897 private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001898 String[] outError) throws XmlPullParserException, IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001899 final String splitName;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001900 final String pkgName;
1901
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001902 try {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001903 Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001904 pkgName = packageSplit.first;
1905 splitName = packageSplit.second;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001906
1907 if (!TextUtils.isEmpty(splitName)) {
1908 outError[0] = "Expected base APK, but found split " + splitName;
1909 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1910 return null;
1911 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001912 } catch (PackageParserException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001913 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1914 return null;
1915 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001916
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001917 if (mCallback != null) {
1918 String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath);
1919 if (overlayPaths != null && overlayPaths.length > 0) {
1920 for (String overlayPath : overlayPaths) {
1921 res.getAssets().addOverlayPath(overlayPath);
1922 }
1923 }
1924 }
1925
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001926 final Package pkg = new Package(pkgName);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001927
Svet Ganov354cd3c2015-12-17 11:35:04 -08001928 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001929 com.android.internal.R.styleable.AndroidManifest);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001930
Dianne Hackborn3accca02013-09-20 09:32:11 -07001931 pkg.mVersionCode = sa.getInteger(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001932 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001933 pkg.mVersionCodeMajor = sa.getInteger(
1934 com.android.internal.R.styleable.AndroidManifest_versionCodeMajor, 0);
1935 pkg.applicationInfo.versionCode = pkg.getLongVersionCode();
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001936 pkg.baseRevisionCode = sa.getInteger(
1937 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001938 pkg.mVersionName = sa.getNonConfigurationString(
1939 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001940 if (pkg.mVersionName != null) {
1941 pkg.mVersionName = pkg.mVersionName.intern();
1942 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001943
1944 pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
1945
Alan Viveretteb6a25732017-11-21 14:49:24 -05001946 pkg.mCompileSdkVersion = sa.getInteger(
1947 com.android.internal.R.styleable.AndroidManifest_compileSdkVersion, 0);
1948 pkg.applicationInfo.compileSdkVersion = pkg.mCompileSdkVersion;
1949 pkg.mCompileSdkVersionCodename = sa.getNonConfigurationString(
1950 com.android.internal.R.styleable.AndroidManifest_compileSdkVersionCodename, 0);
1951 if (pkg.mCompileSdkVersionCodename != null) {
1952 pkg.mCompileSdkVersionCodename = pkg.mCompileSdkVersionCodename.intern();
1953 }
1954 pkg.applicationInfo.compileSdkVersionCodename = pkg.mCompileSdkVersionCodename;
1955
Svet Ganov354cd3c2015-12-17 11:35:04 -08001956 sa.recycle();
1957
1958 return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
1959 }
1960
1961 /**
1962 * This is the common parsing routing for handling parent and child
1963 * packages in a base APK. The difference between parent and child
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001964 * parsing is that some tags are not supported by child packages as
Svet Ganov354cd3c2015-12-17 11:35:04 -08001965 * well as some manifest attributes are ignored. The implementation
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001966 * assumes the calling code has already handled the manifest tag if needed
Svet Ganov354cd3c2015-12-17 11:35:04 -08001967 * (this applies to the parent only).
1968 *
1969 * @param pkg The package which to populate
1970 * @param acceptedTags Which tags to handle, null to handle all
1971 * @param res Resources against which to resolve values
1972 * @param parser Parser of the manifest
1973 * @param flags Flags about how to parse
1974 * @param outError Human readable error if parsing fails
1975 * @return The package if parsing succeeded or null.
1976 *
1977 * @throws XmlPullParserException
1978 * @throws IOException
1979 */
1980 private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
1981 XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
1982 IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001983 mParseInstrumentationArgs = null;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001984
1985 int type;
1986 boolean foundApp = false;
1987
1988 TypedArray sa = res.obtainAttributes(parser,
1989 com.android.internal.R.styleable.AndroidManifest);
1990
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001991 String str = sa.getNonConfigurationString(
1992 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
1993 if (str != null && str.length() > 0) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001994 String nameError = validateName(str, true, false);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001995 if (nameError != null && !"android".equals(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001996 outError[0] = "<manifest> specifies bad sharedUserId name \""
1997 + str + "\": " + nameError;
1998 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
1999 return null;
2000 }
2001 pkg.mSharedUserId = str.intern();
2002 pkg.mSharedUserLabel = sa.getResourceId(
2003 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
2004 }
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -08002005
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08002006 pkg.installLocation = sa.getInteger(
2007 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07002008 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002009 pkg.applicationInfo.installLocation = pkg.installLocation;
Kenny Root7cb9be22012-05-30 15:30:37 -07002010
Todd Kennedy11e45072017-01-25 13:24:21 -08002011 final int targetSandboxVersion = sa.getInteger(
2012 com.android.internal.R.styleable.AndroidManifest_targetSandboxVersion,
2013 PARSE_DEFAULT_TARGET_SANDBOX);
2014 pkg.applicationInfo.targetSandboxVersion = targetSandboxVersion;
Alan Viverettefd274a02014-03-27 15:39:15 -07002015
Kenny Root7cb9be22012-05-30 15:30:37 -07002016 /* Set the global "forward lock" flag */
2017 if ((flags & PARSE_FORWARD_LOCK) != 0) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08002018 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
Kenny Root7cb9be22012-05-30 15:30:37 -07002019 }
2020
2021 /* Set the global "on SD card" flag */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07002022 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
Kenny Root7cb9be22012-05-30 15:30:37 -07002023 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
2024 }
2025
Adam Lesinski4e862812016-11-21 16:02:24 -08002026 if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) {
2027 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
2028 }
2029
Dianne Hackborn723738c2009-06-25 19:48:04 -07002030 // Resource boolean are -1, so 1 means we don't know the value.
2031 int supportsSmallScreens = 1;
2032 int supportsNormalScreens = 1;
2033 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002034 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002035 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002036 int anyDensity = 1;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002038 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -07002039 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2040 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2041 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002042 continue;
2043 }
2044
2045 String tagName = parser.getName();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002046
2047 if (acceptedTags != null && !acceptedTags.contains(tagName)) {
2048 Slog.w(TAG, "Skipping unsupported element under <manifest>: "
2049 + tagName + " at " + mArchiveSourcePath + " "
2050 + parser.getPositionDescription());
2051 XmlUtils.skipCurrentTag(parser);
2052 continue;
2053 }
2054
2055 if (tagName.equals(TAG_APPLICATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002056 if (foundApp) {
2057 if (RIGID_PARSER) {
2058 outError[0] = "<manifest> has more than one <application>";
2059 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2060 return null;
2061 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002062 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002063 XmlUtils.skipCurrentTag(parser);
2064 continue;
2065 }
2066 }
2067
2068 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002069 if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002070 return null;
2071 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002072 } else if (tagName.equals(TAG_OVERLAY)) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002073 sa = res.obtainAttributes(parser,
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002074 com.android.internal.R.styleable.AndroidManifestResourceOverlay);
2075 pkg.mOverlayTarget = sa.getString(
2076 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002077 pkg.mOverlayPriority = sa.getInt(
2078 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
2079 0);
Adam Lesinskie7334972018-01-17 16:13:52 -08002080 pkg.mOverlayIsStatic = sa.getBoolean(
Jaekyun Seok04342892017-03-02 15:24:19 +09002081 com.android.internal.R.styleable.AndroidManifestResourceOverlay_isStatic,
2082 false);
Todd Leeea2f3be2017-03-16 14:00:52 -07002083 final String propName = sa.getString(
2084 com.android.internal.R.styleable
2085 .AndroidManifestResourceOverlay_requiredSystemPropertyName);
2086 final String propValue = sa.getString(
2087 com.android.internal.R.styleable
2088 .AndroidManifestResourceOverlay_requiredSystemPropertyValue);
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002089 sa.recycle();
2090
2091 if (pkg.mOverlayTarget == null) {
2092 outError[0] = "<overlay> does not specify a target package";
2093 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2094 return null;
2095 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002096
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002097 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
2098 outError[0] = "<overlay> priority must be between 0 and 9999";
2099 mParseError =
2100 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2101 return null;
2102 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002103
2104 // check to see if overlay should be excluded based on system property condition
2105 if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
2106 Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and "
2107 + pkg.baseCodePath+ ": overlay ignored due to required system property: "
2108 + propName + " with value: " + propValue);
2109 return null;
Jaekyun Seok04342892017-03-02 15:24:19 +09002110 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002111
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002112 XmlUtils.skipCurrentTag(parser);
2113
Svet Ganov354cd3c2015-12-17 11:35:04 -08002114 } else if (tagName.equals(TAG_KEY_SETS)) {
2115 if (!parseKeySets(pkg, res, parser, outError)) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08002116 return null;
2117 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002118 } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002119 if (!parsePermissionGroup(pkg, flags, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002120 return null;
2121 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002122 } else if (tagName.equals(TAG_PERMISSION)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002123 if (!parsePermission(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002124 return null;
2125 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002126 } else if (tagName.equals(TAG_PERMISSION_TREE)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002127 if (!parsePermissionTree(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002128 return null;
2129 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002130 } else if (tagName.equals(TAG_USES_PERMISSION)) {
2131 if (!parseUsesPermission(pkg, res, parser)) {
Svetoslav96a77162015-04-03 13:58:33 -07002132 return null;
2133 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002134 } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
2135 || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
2136 if (!parseUsesPermission(pkg, res, parser)) {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002137 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002138 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002139 } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002140 ConfigurationInfo cPref = new ConfigurationInfo();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002141 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
2143 cPref.reqTouchScreen = sa.getInt(
2144 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
2145 Configuration.TOUCHSCREEN_UNDEFINED);
2146 cPref.reqKeyboardType = sa.getInt(
2147 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
2148 Configuration.KEYBOARD_UNDEFINED);
2149 if (sa.getBoolean(
2150 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
2151 false)) {
2152 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
2153 }
2154 cPref.reqNavigation = sa.getInt(
2155 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
2156 Configuration.NAVIGATION_UNDEFINED);
2157 if (sa.getBoolean(
2158 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
2159 false)) {
2160 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
2161 }
2162 sa.recycle();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002163 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002164
2165 XmlUtils.skipCurrentTag(parser);
2166
Svet Ganov354cd3c2015-12-17 11:35:04 -08002167 } else if (tagName.equals(TAG_USES_FEATURE)) {
2168 FeatureInfo fi = parseUsesFeature(res, parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002169 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
2170
Dianne Hackborn49237342009-08-27 20:08:01 -07002171 if (fi.name == null) {
2172 ConfigurationInfo cPref = new ConfigurationInfo();
2173 cPref.reqGlEsVersion = fi.reqGlEsVersion;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002174 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
Dianne Hackborn49237342009-08-27 20:08:01 -07002175 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07002176
2177 XmlUtils.skipCurrentTag(parser);
2178
Svet Ganov354cd3c2015-12-17 11:35:04 -08002179 } else if (tagName.equals(TAG_FEATURE_GROUP)) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002180 FeatureGroupInfo group = new FeatureGroupInfo();
2181 ArrayList<FeatureInfo> features = null;
2182 final int innerDepth = parser.getDepth();
2183 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2184 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
2185 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2186 continue;
2187 }
Adam Lesinski2c72b682014-06-24 09:56:01 -07002188
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002189 final String innerTagName = parser.getName();
2190 if (innerTagName.equals("uses-feature")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002191 FeatureInfo featureInfo = parseUsesFeature(res, parser);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002192 // FeatureGroups are stricter and mandate that
2193 // any <uses-feature> declared are mandatory.
2194 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
2195 features = ArrayUtils.add(features, featureInfo);
2196 } else {
2197 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
2198 " at " + mArchiveSourcePath + " " +
2199 parser.getPositionDescription());
2200 }
2201 XmlUtils.skipCurrentTag(parser);
2202 }
2203
2204 if (features != null) {
2205 group.features = new FeatureInfo[features.size()];
2206 group.features = features.toArray(group.features);
2207 }
2208 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
Adam Lesinski2c72b682014-06-24 09:56:01 -07002209
Svet Ganov354cd3c2015-12-17 11:35:04 -08002210 } else if (tagName.equals(TAG_USES_SDK)) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07002211 if (SDK_VERSION > 0) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002212 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002213 com.android.internal.R.styleable.AndroidManifestUsesSdk);
2214
Todd Kennedy4f657082016-06-28 10:31:05 -07002215 int minVers = 1;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002216 String minCode = null;
2217 int targetVers = 0;
2218 String targetCode = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002219
Dianne Hackborn851a5412009-05-08 12:06:44 -07002220 TypedValue val = sa.peekValue(
2221 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
2222 if (val != null) {
2223 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
2224 targetCode = minCode = val.string.toString();
2225 } else {
2226 // If it's not a string, it's an integer.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002227 targetVers = minVers = val.data;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002228 }
2229 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002230
Dianne Hackborn851a5412009-05-08 12:06:44 -07002231 val = sa.peekValue(
2232 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
2233 if (val != null) {
2234 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
Todd Kennedy89d60182016-03-11 11:18:32 -08002235 targetCode = val.string.toString();
2236 if (minCode == null) {
2237 minCode = targetCode;
2238 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002239 } else {
2240 // If it's not a string, it's an integer.
2241 targetVers = val.data;
2242 }
2243 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002245 sa.recycle();
2246
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002247 final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers, minCode,
2248 SDK_VERSION, SDK_CODENAMES, outError);
2249 if (minSdkVersion < 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002250 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2251 return null;
2252 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002253
Patrick Baumannccb20b82018-01-08 13:22:46 -08002254 boolean defaultToCurrentDevBranch = (flags & PARSE_FORCE_SDK) != 0;
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002255 final int targetSdkVersion = PackageParser.computeTargetSdkVersion(targetVers,
Patrick Baumannccb20b82018-01-08 13:22:46 -08002256 targetCode, SDK_CODENAMES, outError, defaultToCurrentDevBranch);
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002257 if (targetSdkVersion < 0) {
2258 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2259 return null;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002260 }
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002261
2262 pkg.applicationInfo.minSdkVersion = minSdkVersion;
2263 pkg.applicationInfo.targetSdkVersion = targetSdkVersion;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002264 }
2265
2266 XmlUtils.skipCurrentTag(parser);
2267
Svet Ganov354cd3c2015-12-17 11:35:04 -08002268 } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
2269 sa = res.obtainAttributes(parser,
Dianne Hackborn723738c2009-06-25 19:48:04 -07002270 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
2271
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002272 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
2273 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
2274 0);
2275 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
2276 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
2277 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07002278 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
2279 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
2280 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002281
Dianne Hackborn723738c2009-06-25 19:48:04 -07002282 // This is a trick to get a boolean and still able to detect
2283 // if a value was actually set.
2284 supportsSmallScreens = sa.getInteger(
2285 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
2286 supportsSmallScreens);
2287 supportsNormalScreens = sa.getInteger(
2288 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
2289 supportsNormalScreens);
2290 supportsLargeScreens = sa.getInteger(
2291 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
2292 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002293 supportsXLargeScreens = sa.getInteger(
2294 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
2295 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002296 resizeable = sa.getInteger(
2297 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002298 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002299 anyDensity = sa.getInteger(
2300 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
2301 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07002302
2303 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002304
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07002305 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002306
Svet Ganov354cd3c2015-12-17 11:35:04 -08002307 } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
2308 sa = res.obtainAttributes(parser,
Dianne Hackborn854060af2009-07-09 18:14:31 -07002309 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
2310
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002311 // Note: don't allow this value to be a reference to a resource
2312 // that may change.
Dianne Hackborn854060af2009-07-09 18:14:31 -07002313 String name = sa.getNonResourceString(
2314 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
2315
2316 sa.recycle();
2317
Todd Kennedy232d29e2017-11-06 14:45:53 -08002318 if (name != null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002319 if (pkg.protectedBroadcasts == null) {
2320 pkg.protectedBroadcasts = new ArrayList<String>();
2321 }
2322 if (!pkg.protectedBroadcasts.contains(name)) {
2323 pkg.protectedBroadcasts.add(name.intern());
2324 }
2325 }
2326
2327 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002328
Svet Ganov354cd3c2015-12-17 11:35:04 -08002329 } else if (tagName.equals(TAG_INSTRUMENTATION)) {
2330 if (parseInstrumentation(pkg, res, parser, outError) == null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002331 return null;
2332 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002333 } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
2334 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002335 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2336
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002337 String orig =sa.getNonConfigurationString(
2338 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002339 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002340 if (pkg.mOriginalPackages == null) {
2341 pkg.mOriginalPackages = new ArrayList<String>();
2342 pkg.mRealPackage = pkg.packageName;
2343 }
2344 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002345 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002346
2347 sa.recycle();
2348
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002349 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002350
Svet Ganov354cd3c2015-12-17 11:35:04 -08002351 } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
2352 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002353 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2354
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002355 String name = sa.getNonConfigurationString(
2356 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002357
2358 sa.recycle();
2359
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002360 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002361 if (pkg.mAdoptPermissions == null) {
2362 pkg.mAdoptPermissions = new ArrayList<String>();
2363 }
2364 pkg.mAdoptPermissions.add(name);
2365 }
2366
2367 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002368
Svet Ganov354cd3c2015-12-17 11:35:04 -08002369 } else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002370 // Just skip this tag
2371 XmlUtils.skipCurrentTag(parser);
2372 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002373
Svet Ganov354cd3c2015-12-17 11:35:04 -08002374 } else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002375 // Just skip this tag
2376 XmlUtils.skipCurrentTag(parser);
2377 continue;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002378 } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
Michael Wrighteaeb1902013-09-05 18:15:57 -07002379 XmlUtils.skipCurrentTag(parser);
2380 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002381
Svet Ganov354cd3c2015-12-17 11:35:04 -08002382 } else if (tagName.equals(TAG_EAT_COMMENT)) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002383 // Just skip this tag
2384 XmlUtils.skipCurrentTag(parser);
2385 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002386
Svet Ganov354cd3c2015-12-17 11:35:04 -08002387 } else if (tagName.equals(TAG_PACKAGE)) {
Svet Ganova7532cf2016-05-02 08:13:17 -07002388 if (!MULTI_PACKAGE_APK_ENABLED) {
2389 XmlUtils.skipCurrentTag(parser);
2390 continue;
2391 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002392 if (!parseBaseApkChild(pkg, res, parser, flags, outError)) {
2393 // If parsing a child failed the error is already set
2394 return null;
2395 }
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002396
2397 } else if (tagName.equals(TAG_RESTRICT_UPDATE)) {
2398 if ((flags & PARSE_IS_SYSTEM_DIR) != 0) {
2399 sa = res.obtainAttributes(parser,
2400 com.android.internal.R.styleable.AndroidManifestRestrictUpdate);
2401 final String hash = sa.getNonConfigurationString(
2402 com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0);
2403 sa.recycle();
2404
2405 pkg.restrictUpdateHash = null;
2406 if (hash != null) {
2407 final int hashLength = hash.length();
2408 final byte[] hashBytes = new byte[hashLength / 2];
2409 for (int i = 0; i < hashLength; i += 2){
2410 hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4)
2411 + Character.digit(hash.charAt(i + 1), 16));
2412 }
2413 pkg.restrictUpdateHash = hashBytes;
2414 }
2415 }
2416
2417 XmlUtils.skipCurrentTag(parser);
2418
Dianne Hackborn854060af2009-07-09 18:14:31 -07002419 } else if (RIGID_PARSER) {
2420 outError[0] = "Bad element under <manifest>: "
2421 + parser.getName();
2422 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2423 return null;
2424
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002425 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002426 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002427 + " at " + mArchiveSourcePath + " "
2428 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002429 XmlUtils.skipCurrentTag(parser);
2430 continue;
2431 }
2432 }
2433
2434 if (!foundApp && pkg.instrumentation.size() == 0) {
2435 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
2436 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
2437 }
2438
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002439 final int NP = PackageParser.NEW_PERMISSIONS.length;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002440 StringBuilder implicitPerms = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002441 for (int ip=0; ip<NP; ip++) {
2442 final PackageParser.NewPermissionInfo npi
2443 = PackageParser.NEW_PERMISSIONS[ip];
2444 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
2445 break;
2446 }
2447 if (!pkg.requestedPermissions.contains(npi.name)) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002448 if (implicitPerms == null) {
2449 implicitPerms = new StringBuilder(128);
2450 implicitPerms.append(pkg.packageName);
2451 implicitPerms.append(": compat added ");
2452 } else {
2453 implicitPerms.append(' ');
2454 }
2455 implicitPerms.append(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002456 pkg.requestedPermissions.add(npi.name);
2457 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002458 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002459 if (implicitPerms != null) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002460 Slog.i(TAG, implicitPerms.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002461 }
Dianne Hackborn79245122012-03-12 10:51:26 -07002462
2463 final int NS = PackageParser.SPLIT_PERMISSIONS.length;
2464 for (int is=0; is<NS; is++) {
2465 final PackageParser.SplitPermissionInfo spi
2466 = PackageParser.SPLIT_PERMISSIONS[is];
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -07002467 if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
2468 || !pkg.requestedPermissions.contains(spi.rootPerm)) {
Dianne Hackborn5e4705a2012-04-06 12:55:53 -07002469 continue;
Dianne Hackborn79245122012-03-12 10:51:26 -07002470 }
2471 for (int in=0; in<spi.newPerms.length; in++) {
2472 final String perm = spi.newPerms[in];
2473 if (!pkg.requestedPermissions.contains(perm)) {
2474 pkg.requestedPermissions.add(perm);
Dianne Hackborn79245122012-03-12 10:51:26 -07002475 }
2476 }
2477 }
2478
Dianne Hackborn723738c2009-06-25 19:48:04 -07002479 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
2480 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002481 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002482 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
2483 }
2484 if (supportsNormalScreens != 0) {
2485 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
2486 }
2487 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
2488 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002489 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002490 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
2491 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002492 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
2493 && pkg.applicationInfo.targetSdkVersion
2494 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
2495 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
2496 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002497 if (resizeable < 0 || (resizeable > 0
2498 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002499 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002500 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
2501 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002502 if (anyDensity < 0 || (anyDensity > 0
2503 && pkg.applicationInfo.targetSdkVersion
2504 >= android.os.Build.VERSION_CODES.DONUT)) {
2505 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07002506 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07002507
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002508 // At this point we can check if an application is not supporting densities and hence
2509 // cannot be windowed / resized. Note that an SDK version of 0 is common for
2510 // pre-Doughnut applications.
2511 if (pkg.applicationInfo.usesCompatibilityMode()) {
Winson Chungd3395382016-12-13 11:49:09 -08002512 adjustPackageToBeUnresizeableAndUnpipable(pkg);
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002513 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002514 return pkg;
2515 }
2516
Todd Leeea2f3be2017-03-16 14:00:52 -07002517 private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
2518
2519 if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
2520 if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
2521 // malformed condition - incomplete
2522 Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName
2523 + "=" + propValue + "' - require both requiredSystemPropertyName"
2524 + " AND requiredSystemPropertyValue to be specified.");
2525 return false;
2526 }
2527 // no valid condition set - so no exclusion criteria, overlay will be included.
2528 return true;
2529 }
2530
2531 // check property value - make sure it is both set and equal to expected value
2532 final String currValue = SystemProperties.get(propName);
2533 return (currValue != null && currValue.equals(propValue));
2534 }
2535
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002536 /**
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002537 * This is a pre-density application which will get scaled - instead of being pixel perfect.
2538 * This type of application is not resizable.
2539 *
2540 * @param pkg The package which needs to be marked as unresizable.
2541 */
Winson Chungd3395382016-12-13 11:49:09 -08002542 private void adjustPackageToBeUnresizeableAndUnpipable(Package pkg) {
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002543 for (Activity a : pkg.activities) {
2544 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -08002545 a.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE;
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002546 }
2547 }
2548
2549 /**
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002550 * Computes the targetSdkVersion to use at runtime. If the package is not
2551 * compatible with this platform, populates {@code outError[0]} with an
2552 * error message.
2553 * <p>
2554 * If {@code targetCode} is not specified, e.g. the value is {@code null},
2555 * then the {@code targetVers} will be returned unmodified.
2556 * <p>
2557 * Otherwise, the behavior varies based on whether the current platform
2558 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2559 * has length > 0:
2560 * <ul>
2561 * <li>If this is a pre-release platform and the value specified by
2562 * {@code targetCode} is contained within the array of allowed pre-release
2563 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2564 * <li>If this is a released platform, this method will return -1 to
2565 * indicate that the package is not compatible with this platform.
2566 * </ul>
2567 *
2568 * @param targetVers targetSdkVersion number, if specified in the
2569 * application manifest, or 0 otherwise
2570 * @param targetCode targetSdkVersion code, if specified in the application
2571 * manifest, or {@code null} otherwise
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002572 * @param platformSdkCodenames array of allowed pre-release SDK codenames
2573 * for this platform
2574 * @param outError output array to populate with error, if applicable
Patrick Baumannccb20b82018-01-08 13:22:46 -08002575 * @param forceCurrentDev if development target code is not available, use the current
2576 * development version by default.
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002577 * @return the targetSdkVersion to use at runtime, or -1 if the package is
2578 * not compatible with this platform
2579 * @hide Exposed for unit testing only.
2580 */
2581 @TestApi
2582 public static int computeTargetSdkVersion(@IntRange(from = 0) int targetVers,
Patrick Baumannccb20b82018-01-08 13:22:46 -08002583 @Nullable String targetCode, @NonNull String[] platformSdkCodenames,
2584 @NonNull String[] outError, boolean forceCurrentDev) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002585 // If it's a release SDK, return the version number unmodified.
2586 if (targetCode == null) {
2587 return targetVers;
2588 }
2589
2590 // If it's a pre-release SDK and the codename matches this platform, it
2591 // definitely targets this SDK.
Patrick Baumannccb20b82018-01-08 13:22:46 -08002592 if (ArrayUtils.contains(platformSdkCodenames, targetCode) || forceCurrentDev) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002593 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2594 }
2595
2596 // Otherwise, we're looking at an incompatible pre-release SDK.
2597 if (platformSdkCodenames.length > 0) {
2598 outError[0] = "Requires development platform " + targetCode
2599 + " (current platform is any of "
2600 + Arrays.toString(platformSdkCodenames) + ")";
2601 } else {
2602 outError[0] = "Requires development platform " + targetCode
2603 + " but this is a release platform.";
2604 }
2605 return -1;
2606 }
2607
2608 /**
2609 * Computes the minSdkVersion to use at runtime. If the package is not
2610 * compatible with this platform, populates {@code outError[0]} with an
2611 * error message.
2612 * <p>
2613 * If {@code minCode} is not specified, e.g. the value is {@code null},
2614 * then behavior varies based on the {@code platformSdkVersion}:
2615 * <ul>
2616 * <li>If the platform SDK version is greater than or equal to the
2617 * {@code minVers}, returns the {@code mniVers} unmodified.
2618 * <li>Otherwise, returns -1 to indicate that the package is not
2619 * compatible with this platform.
2620 * </ul>
2621 * <p>
2622 * Otherwise, the behavior varies based on whether the current platform
2623 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2624 * has length > 0:
2625 * <ul>
2626 * <li>If this is a pre-release platform and the value specified by
2627 * {@code targetCode} is contained within the array of allowed pre-release
2628 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2629 * <li>If this is a released platform, this method will return -1 to
2630 * indicate that the package is not compatible with this platform.
2631 * </ul>
2632 *
2633 * @param minVers minSdkVersion number, if specified in the application
2634 * manifest, or 1 otherwise
2635 * @param minCode minSdkVersion code, if specified in the application
2636 * manifest, or {@code null} otherwise
2637 * @param platformSdkVersion platform SDK version number, typically
2638 * Build.VERSION.SDK_INT
2639 * @param platformSdkCodenames array of allowed prerelease SDK codenames
2640 * for this platform
2641 * @param outError output array to populate with error, if applicable
2642 * @return the minSdkVersion to use at runtime, or -1 if the package is not
2643 * compatible with this platform
2644 * @hide Exposed for unit testing only.
2645 */
2646 @TestApi
2647 public static int computeMinSdkVersion(@IntRange(from = 1) int minVers,
2648 @Nullable String minCode, @IntRange(from = 1) int platformSdkVersion,
2649 @NonNull String[] platformSdkCodenames, @NonNull String[] outError) {
2650 // If it's a release SDK, make sure we meet the minimum SDK requirement.
2651 if (minCode == null) {
2652 if (minVers <= platformSdkVersion) {
2653 return minVers;
2654 }
2655
2656 // We don't meet the minimum SDK requirement.
2657 outError[0] = "Requires newer sdk version #" + minVers
2658 + " (current version is #" + platformSdkVersion + ")";
2659 return -1;
2660 }
2661
2662 // If it's a pre-release SDK and the codename matches this platform, we
2663 // definitely meet the minimum SDK requirement.
2664 if (ArrayUtils.contains(platformSdkCodenames, minCode)) {
2665 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2666 }
2667
2668 // Otherwise, we're looking at an incompatible pre-release SDK.
2669 if (platformSdkCodenames.length > 0) {
2670 outError[0] = "Requires development platform " + minCode
2671 + " (current platform is any of "
2672 + Arrays.toString(platformSdkCodenames) + ")";
2673 } else {
2674 outError[0] = "Requires development platform " + minCode
2675 + " but this is a release platform.";
2676 }
2677 return -1;
2678 }
2679
Todd Kennedy27c24fb2015-09-17 16:49:25 -07002680 private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002681 FeatureInfo fi = new FeatureInfo();
2682 TypedArray sa = res.obtainAttributes(attrs,
2683 com.android.internal.R.styleable.AndroidManifestUsesFeature);
2684 // Note: don't allow this value to be a reference to a resource
2685 // that may change.
2686 fi.name = sa.getNonResourceString(
2687 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
Jeff Sharkey115d2c12016-02-15 17:25:57 -07002688 fi.version = sa.getInt(
2689 com.android.internal.R.styleable.AndroidManifestUsesFeature_version, 0);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002690 if (fi.name == null) {
2691 fi.reqGlEsVersion = sa.getInt(
2692 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
2693 FeatureInfo.GL_ES_VERSION_UNDEFINED);
2694 }
2695 if (sa.getBoolean(
2696 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) {
2697 fi.flags |= FeatureInfo.FLAG_REQUIRED;
2698 }
2699 sa.recycle();
2700 return fi;
2701 }
2702
Svet Ganov67882122016-12-11 16:36:34 -08002703 private boolean parseUsesStaticLibrary(Package pkg, Resources res, XmlResourceParser parser,
2704 String[] outError) throws XmlPullParserException, IOException {
2705 TypedArray sa = res.obtainAttributes(parser,
2706 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary);
2707
2708 // Note: don't allow this value to be a reference to a resource that may change.
2709 String lname = sa.getNonResourceString(
2710 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
2711 final int version = sa.getInt(
2712 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary_version, -1);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002713 String certSha256Digest = sa.getNonResourceString(com.android.internal.R.styleable
Svet Ganov67882122016-12-11 16:36:34 -08002714 .AndroidManifestUsesStaticLibrary_certDigest);
2715 sa.recycle();
2716
2717 // Since an APK providing a static shared lib can only provide the lib - fail if malformed
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002718 if (lname == null || version < 0 || certSha256Digest == null) {
Svet Ganov67882122016-12-11 16:36:34 -08002719 outError[0] = "Bad uses-static-library declaration name: " + lname + " version: "
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002720 + version + " certDigest" + certSha256Digest;
Svet Ganov67882122016-12-11 16:36:34 -08002721 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2722 XmlUtils.skipCurrentTag(parser);
2723 return false;
2724 }
2725
2726 // Can depend only on one version of the same library
2727 if (pkg.usesStaticLibraries != null && pkg.usesStaticLibraries.contains(lname)) {
2728 outError[0] = "Depending on multiple versions of static library " + lname;
2729 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2730 XmlUtils.skipCurrentTag(parser);
2731 return false;
2732 }
2733
2734 lname = lname.intern();
2735 // We allow ":" delimiters in the SHA declaration as this is the format
2736 // emitted by the certtool making it easy for developers to copy/paste.
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002737 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2738
2739 // Fot apps targeting O-MR1 we require explicit enumeration of all certs.
2740 String[] additionalCertSha256Digests = EmptyArray.STRING;
2741 if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.O) {
2742 additionalCertSha256Digests = parseAdditionalCertificates(res, parser, outError);
2743 if (additionalCertSha256Digests == null) {
2744 return false;
2745 }
2746 } else {
2747 XmlUtils.skipCurrentTag(parser);
2748 }
2749
2750 final String[] certSha256Digests = new String[additionalCertSha256Digests.length + 1];
2751 certSha256Digests[0] = certSha256Digest;
2752 System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests,
2753 1, additionalCertSha256Digests.length);
2754
Svet Ganov67882122016-12-11 16:36:34 -08002755 pkg.usesStaticLibraries = ArrayUtils.add(pkg.usesStaticLibraries, lname);
Dianne Hackborn3accca02013-09-20 09:32:11 -07002756 pkg.usesStaticLibrariesVersions = ArrayUtils.appendLong(
Svet Ganov8a10ef52017-02-16 20:58:09 -08002757 pkg.usesStaticLibrariesVersions, version, true);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002758 pkg.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String[].class,
2759 pkg.usesStaticLibrariesCertDigests, certSha256Digests, true);
Svet Ganov67882122016-12-11 16:36:34 -08002760
2761 return true;
2762 }
2763
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002764 private String[] parseAdditionalCertificates(Resources resources, XmlResourceParser parser,
2765 String[] outError) throws XmlPullParserException, IOException {
2766 String[] certSha256Digests = EmptyArray.STRING;
2767
2768 int outerDepth = parser.getDepth();
2769 int type;
2770 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2771 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2772 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2773 continue;
2774 }
2775
2776 final String nodeName = parser.getName();
2777 if (nodeName.equals("additional-certificate")) {
2778 final TypedArray sa = resources.obtainAttributes(parser, com.android.internal.
2779 R.styleable.AndroidManifestAdditionalCertificate);
2780 String certSha256Digest = sa.getNonResourceString(com.android.internal.
2781 R.styleable.AndroidManifestAdditionalCertificate_certDigest);
2782 sa.recycle();
2783
2784 if (TextUtils.isEmpty(certSha256Digest)) {
2785 outError[0] = "Bad additional-certificate declaration with empty"
2786 + " certDigest:" + certSha256Digest;
2787 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2788 XmlUtils.skipCurrentTag(parser);
2789 sa.recycle();
2790 return null;
2791 }
2792
2793 // We allow ":" delimiters in the SHA declaration as this is the format
2794 // emitted by the certtool making it easy for developers to copy/paste.
2795 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2796 certSha256Digests = ArrayUtils.appendElement(String.class,
2797 certSha256Digests, certSha256Digest);
2798 } else {
2799 XmlUtils.skipCurrentTag(parser);
2800 }
2801 }
2802
2803 return certSha256Digests;
2804 }
2805
Svet Ganov354cd3c2015-12-17 11:35:04 -08002806 private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
2807 throws XmlPullParserException, IOException {
2808 TypedArray sa = res.obtainAttributes(parser,
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002809 com.android.internal.R.styleable.AndroidManifestUsesPermission);
2810
2811 // Note: don't allow this value to be a reference to a resource
2812 // that may change.
2813 String name = sa.getNonResourceString(
2814 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002815
Christopher Tatefb0676a2013-09-16 16:34:52 -07002816 int maxSdkVersion = 0;
2817 TypedValue val = sa.peekValue(
2818 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
2819 if (val != null) {
2820 if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
2821 maxSdkVersion = val.data;
2822 }
2823 }
2824
Dianne Hackborncd154e92017-02-28 17:37:35 -08002825 final String requiredFeature = sa.getNonConfigurationString(
2826 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredFeature, 0);
2827
2828 final String requiredNotfeature = sa.getNonConfigurationString(
2829 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);
2830
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002831 sa.recycle();
2832
Dianne Hackborncd154e92017-02-28 17:37:35 -08002833 XmlUtils.skipCurrentTag(parser);
2834
2835 if (name == null) {
2836 return true;
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002837 }
2838
Dianne Hackborncd154e92017-02-28 17:37:35 -08002839 if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) {
2840 return true;
2841 }
2842
2843 // Only allow requesting this permission if the platform supports the given feature.
2844 if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(requiredFeature)) {
2845 return true;
2846 }
2847
2848 // Only allow requesting this permission if the platform doesn't support the given feature.
2849 if (requiredNotfeature != null && mCallback != null
2850 && mCallback.hasFeature(requiredNotfeature)) {
2851 return true;
2852 }
2853
2854 int index = pkg.requestedPermissions.indexOf(name);
2855 if (index == -1) {
2856 pkg.requestedPermissions.add(name.intern());
2857 } else {
2858 Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
2859 + name + " in package: " + pkg.packageName + " at: "
2860 + parser.getPositionDescription());
2861 }
2862
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002863 return true;
2864 }
2865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002866 private static String buildClassName(String pkg, CharSequence clsSeq,
2867 String[] outError) {
2868 if (clsSeq == null || clsSeq.length() <= 0) {
2869 outError[0] = "Empty class name in package " + pkg;
2870 return null;
2871 }
2872 String cls = clsSeq.toString();
2873 char c = cls.charAt(0);
2874 if (c == '.') {
Narayan Kamath07ac1442017-02-10 15:08:07 +00002875 return pkg + cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002876 }
2877 if (cls.indexOf('.') < 0) {
2878 StringBuilder b = new StringBuilder(pkg);
2879 b.append('.');
2880 b.append(cls);
Narayan Kamath07ac1442017-02-10 15:08:07 +00002881 return b.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002882 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002883 return cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002884 }
2885
2886 private static String buildCompoundName(String pkg,
2887 CharSequence procSeq, String type, String[] outError) {
2888 String proc = procSeq.toString();
2889 char c = proc.charAt(0);
2890 if (pkg != null && c == ':') {
2891 if (proc.length() < 2) {
2892 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
2893 + ": must be at least two characters";
2894 return null;
2895 }
2896 String subName = proc.substring(1);
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002897 String nameError = validateName(subName, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002898 if (nameError != null) {
2899 outError[0] = "Invalid " + type + " name " + proc + " in package "
2900 + pkg + ": " + nameError;
2901 return null;
2902 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002903 return pkg + proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002904 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002905 String nameError = validateName(proc, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002906 if (nameError != null && !"system".equals(proc)) {
2907 outError[0] = "Invalid " + type + " name " + proc + " in package "
2908 + pkg + ": " + nameError;
2909 return null;
2910 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002911 return proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002912 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002913
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002914 private static String buildProcessName(String pkg, String defProc,
2915 CharSequence procSeq, int flags, String[] separateProcesses,
2916 String[] outError) {
2917 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
2918 return defProc != null ? defProc : pkg;
2919 }
2920 if (separateProcesses != null) {
2921 for (int i=separateProcesses.length-1; i>=0; i--) {
2922 String sp = separateProcesses[i];
2923 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
2924 return pkg;
2925 }
2926 }
2927 }
2928 if (procSeq == null || procSeq.length() <= 0) {
2929 return defProc;
2930 }
Makoto Onuki812d188a2017-08-07 09:58:23 -07002931 return TextUtils.safeIntern(buildCompoundName(pkg, procSeq, "process", outError));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002932 }
2933
2934 private static String buildTaskAffinityName(String pkg, String defProc,
2935 CharSequence procSeq, String[] outError) {
2936 if (procSeq == null) {
2937 return defProc;
2938 }
2939 if (procSeq.length() <= 0) {
2940 return null;
2941 }
2942 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
2943 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002944
dcashman989eb3712014-06-17 12:56:12 -07002945 private boolean parseKeySets(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002946 XmlResourceParser parser, String[] outError)
Geremy Condraf1bcca82013-01-07 22:35:24 -08002947 throws XmlPullParserException, IOException {
dcashman989eb3712014-06-17 12:56:12 -07002948 // we've encountered the 'key-sets' tag
Geremy Condraf1bcca82013-01-07 22:35:24 -08002949 // all the keys and keysets that we want must be defined here
2950 // so we're going to iterate over the parser and pull out the things we want
2951 int outerDepth = parser.getDepth();
dcashman989eb3712014-06-17 12:56:12 -07002952 int currentKeySetDepth = -1;
Geremy Condraf1bcca82013-01-07 22:35:24 -08002953 int type;
dcashman989eb3712014-06-17 12:56:12 -07002954 String currentKeySet = null;
2955 ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
2956 ArraySet<String> upgradeKeySets = new ArraySet<String>();
2957 ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
2958 ArraySet<String> improperKeySets = new ArraySet<String>();
Geremy Condraf1bcca82013-01-07 22:35:24 -08002959 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2960 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2961 if (type == XmlPullParser.END_TAG) {
dcashman989eb3712014-06-17 12:56:12 -07002962 if (parser.getDepth() == currentKeySetDepth) {
2963 currentKeySet = null;
2964 currentKeySetDepth = -1;
Kenny Root37dca152013-07-10 14:01:49 -07002965 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002966 continue;
2967 }
dcashman989eb3712014-06-17 12:56:12 -07002968 String tagName = parser.getName();
2969 if (tagName.equals("key-set")) {
2970 if (currentKeySet != null) {
dcashman5db0cd42015-05-22 15:24:40 -07002971 outError[0] = "Improperly nested 'key-set' tag at "
2972 + parser.getPositionDescription();
2973 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002974 return false;
2975 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002976 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002977 com.android.internal.R.styleable.AndroidManifestKeySet);
2978 final String keysetName = sa.getNonResourceString(
2979 com.android.internal.R.styleable.AndroidManifestKeySet_name);
2980 definedKeySets.put(keysetName, new ArraySet<String>());
2981 currentKeySet = keysetName;
2982 currentKeySetDepth = parser.getDepth();
2983 sa.recycle();
2984 } else if (tagName.equals("public-key")) {
2985 if (currentKeySet == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002986 outError[0] = "Improperly nested 'key-set' tag at "
2987 + parser.getPositionDescription();
2988 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002989 return false;
2990 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002991 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002992 com.android.internal.R.styleable.AndroidManifestPublicKey);
2993 final String publicKeyName = sa.getNonResourceString(
2994 com.android.internal.R.styleable.AndroidManifestPublicKey_name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08002995 final String encodedKey = sa.getNonResourceString(
dcashman989eb3712014-06-17 12:56:12 -07002996 com.android.internal.R.styleable.AndroidManifestPublicKey_value);
2997 if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002998 outError[0] = "'public-key' " + publicKeyName + " must define a public-key value"
2999 + " on first use at " + parser.getPositionDescription();
3000 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Kenny Root37dca152013-07-10 14:01:49 -07003001 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003002 return false;
3003 } else if (encodedKey != null) {
3004 PublicKey currentKey = parsePublicKey(encodedKey);
3005 if (currentKey == null) {
3006 Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
3007 + parser.getPositionDescription() + " key-set " + currentKeySet
3008 + " will not be added to the package's defined key-sets.");
3009 sa.recycle();
3010 improperKeySets.add(currentKeySet);
3011 XmlUtils.skipCurrentTag(parser);
3012 continue;
3013 }
3014 if (publicKeys.get(publicKeyName) == null
3015 || publicKeys.get(publicKeyName).equals(currentKey)) {
3016
3017 /* public-key first definition, or matches old definition */
3018 publicKeys.put(publicKeyName, currentKey);
3019 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003020 outError[0] = "Value of 'public-key' " + publicKeyName
dcashman989eb3712014-06-17 12:56:12 -07003021 + " conflicts with previously defined value at "
dcashman5db0cd42015-05-22 15:24:40 -07003022 + parser.getPositionDescription();
3023 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003024 sa.recycle();
3025 return false;
3026 }
Kenny Root37dca152013-07-10 14:01:49 -07003027 }
dcashman989eb3712014-06-17 12:56:12 -07003028 definedKeySets.get(currentKeySet).add(publicKeyName);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003029 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003030 XmlUtils.skipCurrentTag(parser);
3031 } else if (tagName.equals("upgrade-key-set")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003032 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003033 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
3034 String name = sa.getNonResourceString(
3035 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
3036 upgradeKeySets.add(name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003037 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003038 XmlUtils.skipCurrentTag(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003039 } else if (RIGID_PARSER) {
dcashman5db0cd42015-05-22 15:24:40 -07003040 outError[0] = "Bad element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003041 + " at " + mArchiveSourcePath + " "
dcashman5db0cd42015-05-22 15:24:40 -07003042 + parser.getPositionDescription();
3043 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Geremy Condraf1bcca82013-01-07 22:35:24 -08003044 return false;
3045 } else {
dcashman989eb3712014-06-17 12:56:12 -07003046 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003047 + " at " + mArchiveSourcePath + " "
3048 + parser.getPositionDescription());
3049 XmlUtils.skipCurrentTag(parser);
3050 continue;
3051 }
3052 }
dcashman989eb3712014-06-17 12:56:12 -07003053 Set<String> publicKeyNames = publicKeys.keySet();
3054 if (publicKeyNames.removeAll(definedKeySets.keySet())) {
dcashman5db0cd42015-05-22 15:24:40 -07003055 outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
3056 + "'key-set' and 'public-key' names must be distinct.";
3057 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003058 return false;
3059 }
3060 owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
3061 for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) {
3062 final String keySetName = e.getKey();
3063 if (e.getValue().size() == 0) {
3064 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3065 + "'key-set' " + keySetName + " has no valid associated 'public-key'."
3066 + " Not including in package's defined key-sets.");
3067 continue;
3068 } else if (improperKeySets.contains(keySetName)) {
3069 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3070 + "'key-set' " + keySetName + " contained improper 'public-key'"
3071 + " tags. Not including in package's defined key-sets.");
3072 continue;
3073 }
3074 owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
3075 for (String s : e.getValue()) {
3076 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
Geremy Condraf1bcca82013-01-07 22:35:24 -08003077 }
3078 }
dcashman989eb3712014-06-17 12:56:12 -07003079 if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
3080 owner.mUpgradeKeySets = upgradeKeySets;
3081 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003082 outError[0] ="Package" + owner.packageName + " AndroidManifext.xml "
3083 + "does not define all 'upgrade-key-set's .";
3084 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003085 return false;
3086 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003087 return true;
3088 }
3089
Dianne Hackborncd154e92017-02-28 17:37:35 -08003090 private boolean parsePermissionGroup(Package owner, int flags, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003091 XmlResourceParser parser, String[] outError)
3092 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003093 PermissionGroup perm = new PermissionGroup(owner);
3094
Svet Ganov354cd3c2015-12-17 11:35:04 -08003095 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003096 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003097 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003098 "<permission-group>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003099 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
3100 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003101 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003102 com.android.internal.R.styleable.AndroidManifestPermissionGroup_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003103 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
3104 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003105 sa.recycle();
3106 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003107 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003108 }
3109
3110 perm.info.descriptionRes = sa.getResourceId(
3111 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
3112 0);
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003113 perm.info.requestRes = sa.getResourceId(
3114 com.android.internal.R.styleable.AndroidManifestPermissionGroup_request, 0);
Dianne Hackborn7454d3b2012-09-12 17:22:00 -07003115 perm.info.flags = sa.getInt(
3116 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07003117 perm.info.priority = sa.getInt(
3118 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003119
3120 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003121
Svet Ganov354cd3c2015-12-17 11:35:04 -08003122 if (!parseAllMetaData(res, parser, "<permission-group>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003123 outError)) {
3124 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003125 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003126 }
3127
3128 owner.permissionGroups.add(perm);
3129
Dianne Hackborncd154e92017-02-28 17:37:35 -08003130 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003131 }
3132
Dianne Hackborncd154e92017-02-28 17:37:35 -08003133 private boolean parsePermission(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003134 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003135 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003136
Svet Ganov354cd3c2015-12-17 11:35:04 -08003137 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003138 com.android.internal.R.styleable.AndroidManifestPermission);
3139
Dianne Hackborncd154e92017-02-28 17:37:35 -08003140 Permission perm = new Permission(owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003141 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003142 "<permission>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003143 com.android.internal.R.styleable.AndroidManifestPermission_name,
3144 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003145 com.android.internal.R.styleable.AndroidManifestPermission_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003146 com.android.internal.R.styleable.AndroidManifestPermission_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003147 com.android.internal.R.styleable.AndroidManifestPermission_logo,
3148 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003149 sa.recycle();
3150 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003151 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003152 }
3153
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003154 // Note: don't allow this value to be a reference to a resource
3155 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003156 perm.info.group = sa.getNonResourceString(
3157 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
3158 if (perm.info.group != null) {
3159 perm.info.group = perm.info.group.intern();
3160 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 perm.info.descriptionRes = sa.getResourceId(
3163 com.android.internal.R.styleable.AndroidManifestPermission_description,
3164 0);
3165
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003166 perm.info.requestRes = sa.getResourceId(
3167 com.android.internal.R.styleable.AndroidManifestPermission_request, 0);
3168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003169 perm.info.protectionLevel = sa.getInt(
3170 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
3171 PermissionInfo.PROTECTION_NORMAL);
3172
Dianne Hackborn2ca2c872012-09-16 16:03:36 -07003173 perm.info.flags = sa.getInt(
3174 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
3175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003176 sa.recycle();
Dianne Hackborne639da72012-02-21 15:11:13 -08003177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003178 if (perm.info.protectionLevel == -1) {
3179 outError[0] = "<permission> does not specify protectionLevel";
3180 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003181 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003182 }
Dianne Hackborne639da72012-02-21 15:11:13 -08003183
3184 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
3185
3186 if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_FLAGS) != 0) {
Todd Kennedyc247fa12017-06-02 10:29:22 -07003187 if ( (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_INSTANT) == 0
Chad Brubakera5d70a12017-03-23 11:04:50 -07003188 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0
Chad Brubakerc19706a2016-10-13 15:44:59 -07003189 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
Dianne Hackborne639da72012-02-21 15:11:13 -08003190 PermissionInfo.PROTECTION_SIGNATURE) {
Todd Kennedyc247fa12017-06-02 10:29:22 -07003191 outError[0] = "<permission> protectionLevel specifies a non-instnat flag but is "
Dianne Hackborne639da72012-02-21 15:11:13 -08003192 + "not based on signature type";
3193 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003194 return false;
Dianne Hackborne639da72012-02-21 15:11:13 -08003195 }
3196 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003197
Svet Ganov354cd3c2015-12-17 11:35:04 -08003198 if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003199 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003200 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003201 }
3202
3203 owner.permissions.add(perm);
3204
Dianne Hackborncd154e92017-02-28 17:37:35 -08003205 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003206 }
3207
Dianne Hackborncd154e92017-02-28 17:37:35 -08003208 private boolean parsePermissionTree(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003209 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003210 throws XmlPullParserException, IOException {
3211 Permission perm = new Permission(owner);
3212
Svet Ganov354cd3c2015-12-17 11:35:04 -08003213 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003214 com.android.internal.R.styleable.AndroidManifestPermissionTree);
3215
3216 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003217 "<permission-tree>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003218 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
3219 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003220 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003221 com.android.internal.R.styleable.AndroidManifestPermissionTree_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003222 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
3223 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003224 sa.recycle();
3225 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003226 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003227 }
3228
3229 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003231 int index = perm.info.name.indexOf('.');
3232 if (index > 0) {
3233 index = perm.info.name.indexOf('.', index+1);
3234 }
3235 if (index < 0) {
3236 outError[0] = "<permission-tree> name has less than three segments: "
3237 + perm.info.name;
3238 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003239 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003240 }
3241
3242 perm.info.descriptionRes = 0;
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003243 perm.info.requestRes = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003244 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
3245 perm.tree = true;
3246
Svet Ganov354cd3c2015-12-17 11:35:04 -08003247 if (!parseAllMetaData(res, parser, "<permission-tree>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248 outError)) {
3249 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003250 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003251 }
3252
3253 owner.permissions.add(perm);
3254
Dianne Hackborncd154e92017-02-28 17:37:35 -08003255 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003256 }
3257
3258 private Instrumentation parseInstrumentation(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003259 XmlResourceParser parser, String[] outError)
3260 throws XmlPullParserException, IOException {
3261 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003262 com.android.internal.R.styleable.AndroidManifestInstrumentation);
3263
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003264 if (mParseInstrumentationArgs == null) {
3265 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
3266 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
3267 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003268 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003269 com.android.internal.R.styleable.AndroidManifestInstrumentation_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003270 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
3271 com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003272 mParseInstrumentationArgs.tag = "<instrumentation>";
3273 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003274
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003275 mParseInstrumentationArgs.sa = sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003276
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003277 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
3278 new InstrumentationInfo());
3279 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003280 sa.recycle();
3281 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3282 return null;
3283 }
3284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003285 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003286 // Note: don't allow this value to be a reference to a resource
3287 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003288 str = sa.getNonResourceString(
3289 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
3290 a.info.targetPackage = str != null ? str.intern() : null;
3291
Dianne Hackborn34041732017-01-31 15:27:13 -08003292 str = sa.getNonResourceString(
Dianne Hackborn1be53542017-04-28 13:36:00 -07003293 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetProcesses);
3294 a.info.targetProcesses = str != null ? str.intern() : null;
Dianne Hackborn34041732017-01-31 15:27:13 -08003295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003296 a.info.handleProfiling = sa.getBoolean(
3297 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
3298 false);
3299
3300 a.info.functionalTest = sa.getBoolean(
3301 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
3302 false);
3303
3304 sa.recycle();
3305
3306 if (a.info.targetPackage == null) {
3307 outError[0] = "<instrumentation> does not specify targetPackage";
3308 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3309 return null;
3310 }
3311
Svet Ganov354cd3c2015-12-17 11:35:04 -08003312 if (!parseAllMetaData(res, parser, "<instrumentation>", a,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003313 outError)) {
3314 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3315 return null;
3316 }
3317
3318 owner.instrumentation.add(a);
3319
3320 return a;
3321 }
3322
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003323 /**
3324 * Parse the {@code application} XML tree at the current parse location in a
3325 * <em>base APK</em> manifest.
3326 * <p>
3327 * When adding new features, carefully consider if they should also be
3328 * supported by split APKs.
3329 */
3330 private boolean parseBaseApplication(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003331 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003332 throws XmlPullParserException, IOException {
3333 final ApplicationInfo ai = owner.applicationInfo;
3334 final String pkgName = owner.applicationInfo.packageName;
3335
Svet Ganov354cd3c2015-12-17 11:35:04 -08003336 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003337 com.android.internal.R.styleable.AndroidManifestApplication);
3338
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003339 if (!parsePackageItemInfo(owner, ai, outError,
3340 "<application>", sa, false /*nameRequired*/,
3341 com.android.internal.R.styleable.AndroidManifestApplication_name,
3342 com.android.internal.R.styleable.AndroidManifestApplication_label,
3343 com.android.internal.R.styleable.AndroidManifestApplication_icon,
3344 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon,
3345 com.android.internal.R.styleable.AndroidManifestApplication_logo,
3346 com.android.internal.R.styleable.AndroidManifestApplication_banner)) {
3347 sa.recycle();
3348 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3349 return false;
3350 }
3351
3352 if (ai.name != null) {
Todd Kennedyafb52692016-08-22 15:44:00 -07003353 ai.className = ai.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003354 }
3355
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003356 String manageSpaceActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003357 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
3358 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 if (manageSpaceActivity != null) {
3360 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
3361 outError);
3362 }
3363
Christopher Tate181fafa2009-05-14 11:12:14 -07003364 boolean allowBackup = sa.getBoolean(
3365 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
3366 if (allowBackup) {
3367 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07003368
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003369 // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
3370 // and restoreAnyVersion are only relevant if backup is possible for the
3371 // given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003372 String backupAgent = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003373 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
3374 Configuration.NATIVE_CONFIG_VERSION);
Christopher Tate181fafa2009-05-14 11:12:14 -07003375 if (backupAgent != null) {
3376 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07003377 if (DEBUG_BACKUP) {
3378 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003379 + " from " + pkgName + "+" + backupAgent);
3380 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003381
3382 if (sa.getBoolean(
3383 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
3384 true)) {
3385 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
3386 }
3387 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08003388 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
3389 false)) {
3390 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
3391 }
Christopher Tated1de2562014-06-17 17:12:35 -07003392 if (sa.getBoolean(
3393 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
3394 false)) {
3395 ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
3396 }
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003397 if (sa.getBoolean(
3398 com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
3399 false)) {
3400 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
3401 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003402 }
Matthew Williams303650c2015-04-17 18:22:51 -07003403
3404 TypedValue v = sa.peekValue(
3405 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
3406 if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
3407 if (DEBUG_BACKUP) {
3408 Slog.v(TAG, "fullBackupContent specified as boolean=" +
3409 (v.data == 0 ? "false" : "true"));
3410 }
3411 // "false" => -1, "true" => 0
3412 ai.fullBackupContent = (v.data == 0 ? -1 : 0);
3413 }
3414 if (DEBUG_BACKUP) {
3415 Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
3416 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003417 }
Christopher Tate4a627c72011-04-01 14:43:32 -07003418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003419 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08003420 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003421 ai.descriptionRes = sa.getResourceId(
3422 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
3423
Todd Kennedy232d29e2017-11-06 14:45:53 -08003424 if (sa.getBoolean(
3425 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
3426 false)) {
3427 // Check if persistence is based on a feature being present
3428 final String requiredFeature = sa.getNonResourceString(com.android.internal.R.styleable
3429 .AndroidManifestApplication_persistentWhenFeatureAvailable);
3430 if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
3431 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003432 }
Amith Yamasani0d8750d2013-05-01 15:25:28 -07003433 }
3434
3435 if (sa.getBoolean(
3436 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
3437 false)) {
3438 owner.mRequiredForAllUsers = true;
Amith Yamasanie993ae12013-04-15 13:42:57 -07003439 }
3440
3441 String restrictedAccountType = sa.getString(com.android.internal.R.styleable
3442 .AndroidManifestApplication_restrictedAccountType);
3443 if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
3444 owner.mRestrictedAccountType = restrictedAccountType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003445 }
3446
Amith Yamasaniccbe3892013-04-12 17:52:42 -07003447 String requiredAccountType = sa.getString(com.android.internal.R.styleable
3448 .AndroidManifestApplication_requiredAccountType);
3449 if (requiredAccountType != null && requiredAccountType.length() > 0) {
3450 owner.mRequiredAccountType = requiredAccountType;
3451 }
3452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003453 if (sa.getBoolean(
3454 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
3455 false)) {
3456 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
3457 }
3458
3459 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07003460 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08003461 false)) {
3462 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
3463 }
3464
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003465 owner.baseHardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07003466 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07003467 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Alan Viveretted70b9e72015-05-27 14:29:20 -07003468 if (owner.baseHardwareAccelerated) {
3469 ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
3470 }
Romain Guy812ccbe2010-06-01 14:07:24 -07003471
3472 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003473 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
3474 true)) {
3475 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
3476 }
3477
3478 if (sa.getBoolean(
3479 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
3480 false)) {
3481 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
3482 }
3483
3484 if (sa.getBoolean(
3485 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
3486 true)) {
3487 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
3488 }
3489
Svet Ganov354cd3c2015-12-17 11:35:04 -08003490 // The parent package controls installation, hence specify test only installs.
3491 if (owner.parentPackage == null) {
3492 if (sa.getBoolean(
3493 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
3494 false)) {
3495 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
3496 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003497 }
3498
Jason parksa3cdaa52011-01-13 14:15:43 -06003499 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003500 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06003501 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003502 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06003503 }
3504
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003505 if (sa.getBoolean(
Alex Klyubin01a959d2015-03-18 10:05:45 -07003506 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
3507 true)) {
3508 ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
3509 }
3510
3511 if (sa.getBoolean(
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003512 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
3513 false /* default is no RTL support*/)) {
3514 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
3515 }
3516
Narayan Kamath589a1bc2014-07-03 14:43:26 +01003517 if (sa.getBoolean(
3518 com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
3519 false)) {
3520 ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
3521 }
3522
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07003523 if (sa.getBoolean(
3524 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
3525 true)) {
3526 ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
3527 }
3528
Todd Kennedyd022ac22016-04-13 10:49:29 -07003529 if (sa.getBoolean(
3530 R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
3531 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003532 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003533 }
Todd Kennedyd022ac22016-04-13 10:49:29 -07003534 if (sa.getBoolean(
3535 R.styleable.AndroidManifestApplication_directBootAware,
3536 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003537 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003538 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003539
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003540 if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
3541 if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003542 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
3543 } else {
3544 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003545 }
3546 } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003547 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Wale Ogunwale6afdf912016-01-30 13:01:33 -08003548 }
3549
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07003550 ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
3551
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003552 ai.networkSecurityConfigRes = sa.getResourceId(
3553 com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig,
3554 0);
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07003555 ai.category = sa.getInt(
3556 com.android.internal.R.styleable.AndroidManifestApplication_appCategory,
3557 ApplicationInfo.CATEGORY_UNDEFINED);
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003559 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003560 str = sa.getNonConfigurationString(
3561 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003562 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
3563
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003564 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3565 str = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003566 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
3567 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003568 } else {
3569 // Some older apps have been seen to use a resource reference
3570 // here that on older builds was ignored (with a warning). We
3571 // need to continue to do this for them so they don't break.
3572 str = sa.getNonResourceString(
3573 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
3574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003575 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
3576 str, outError);
Jason Monka80bfb52017-11-16 17:15:37 -05003577 String factory = sa.getNonResourceString(
3578 com.android.internal.R.styleable.AndroidManifestApplication_appComponentFactory);
3579 if (factory != null) {
3580 ai.appComponentFactory = buildClassName(ai.packageName, factory, outError);
3581 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003582
3583 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003584 CharSequence pname;
3585 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3586 pname = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003587 com.android.internal.R.styleable.AndroidManifestApplication_process,
3588 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003589 } else {
3590 // Some older apps have been seen to use a resource reference
3591 // here that on older builds was ignored (with a warning). We
3592 // need to continue to do this for them so they don't break.
3593 pname = sa.getNonResourceString(
3594 com.android.internal.R.styleable.AndroidManifestApplication_process);
3595 }
3596 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003597 flags, mSeparateProcesses, outError);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003598
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003599 ai.enabled = sa.getBoolean(
3600 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003601
Jose Lima12d0b4c2014-03-14 16:55:12 -07003602 if (sa.getBoolean(
3603 com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
3604 ai.flags |= ApplicationInfo.FLAG_IS_GAME;
3605 }
3606
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003607 if (sa.getBoolean(
3608 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
3609 false)) {
3610 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07003611
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003612 // A heavy-weight application can not be in a custom process.
3613 // We can do direct compare because we intern all strings.
3614 if (ai.processName != null && !ai.processName.equals(ai.packageName)) {
3615 outError[0] = "cantSaveState applications can not use custom processes";
Dianne Hackborn860755f2010-06-03 18:47:52 -07003616 }
3617 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003618 }
3619
Adam Powell269248d2011-08-02 10:26:54 -07003620 ai.uiOptions = sa.getInt(
3621 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
3622
Narayan Kamath96c11c52017-08-09 13:07:21 +01003623 ai.classLoaderName = sa.getString(
3624 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
3625 if (ai.classLoaderName != null
3626 && !ClassLoaderFactory.isValidClassLoaderName(ai.classLoaderName)) {
3627 outError[0] = "Invalid class loader name: " + ai.classLoaderName;
3628 }
3629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003630 sa.recycle();
3631
3632 if (outError[0] != null) {
3633 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3634 return false;
3635 }
3636
3637 final int innerDepth = parser.getDepth();
Garrett Boyer52136662017-05-23 13:47:58 -07003638 // IMPORTANT: These must only be cached for a single <application> to avoid components
3639 // getting added to the wrong package.
3640 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641 int type;
Bryce Lee22571db2017-07-07 15:54:18 -07003642
Kenny Rootd2d29252011-08-08 11:27:57 -07003643 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3644 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3645 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003646 continue;
3647 }
3648
3649 String tagName = parser.getName();
3650 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003651 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003652 owner.baseHardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003653 if (a == null) {
3654 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3655 return false;
3656 }
3657
3658 owner.activities.add(a);
3659
3660 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003661 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
3662 true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003663 if (a == null) {
3664 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3665 return false;
3666 }
3667
3668 owner.receivers.add(a);
3669
3670 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003671 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003672 if (s == null) {
3673 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3674 return false;
3675 }
3676
3677 owner.services.add(s);
3678
3679 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003680 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003681 if (p == null) {
3682 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3683 return false;
3684 }
3685
3686 owner.providers.add(p);
3687
3688 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003689 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003690 if (a == null) {
3691 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3692 return false;
3693 }
3694
3695 owner.activities.add(a);
3696
3697 } else if (parser.getName().equals("meta-data")) {
3698 // note: application meta-data is stored off to the side, so it can
3699 // remain null in the primary copy (we like to avoid extra copies because
3700 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003701 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003702 outError)) == null) {
3703 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3704 return false;
3705 }
Svet Ganov67882122016-12-11 16:36:34 -08003706 } else if (tagName.equals("static-library")) {
3707 sa = res.obtainAttributes(parser,
3708 com.android.internal.R.styleable.AndroidManifestStaticLibrary);
3709
3710 // Note: don't allow this value to be a reference to a resource
3711 // that may change.
3712 final String lname = sa.getNonResourceString(
3713 com.android.internal.R.styleable.AndroidManifestStaticLibrary_name);
3714 final int version = sa.getInt(
3715 com.android.internal.R.styleable.AndroidManifestStaticLibrary_version, -1);
Dianne Hackborn3accca02013-09-20 09:32:11 -07003716 final int versionMajor = sa.getInt(
3717 com.android.internal.R.styleable.AndroidManifestStaticLibrary_versionMajor,
3718 0);
Svet Ganov67882122016-12-11 16:36:34 -08003719
3720 sa.recycle();
3721
3722 // Since the app canot run without a static lib - fail if malformed
3723 if (lname == null || version < 0) {
3724 outError[0] = "Bad static-library declaration name: " + lname
3725 + " version: " + version;
3726 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3727 XmlUtils.skipCurrentTag(parser);
3728 return false;
3729 }
3730
3731 if (owner.mSharedUserId != null) {
3732 outError[0] = "sharedUserId not allowed in static shared library";
3733 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
3734 XmlUtils.skipCurrentTag(parser);
3735 return false;
3736 }
3737
3738 if (owner.staticSharedLibName != null) {
3739 outError[0] = "Multiple static-shared libs for package " + pkgName;
3740 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3741 XmlUtils.skipCurrentTag(parser);
3742 return false;
3743 }
3744
3745 owner.staticSharedLibName = lname.intern();
Dianne Hackborn3accca02013-09-20 09:32:11 -07003746 if (version >= 0) {
3747 owner.staticSharedLibVersion =
3748 PackageInfo.composeLongVersionCode(versionMajor, version);
3749 } else {
3750 owner.staticSharedLibVersion = version;
3751 }
Svet Ganov67882122016-12-11 16:36:34 -08003752 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY;
3753
3754 XmlUtils.skipCurrentTag(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003755
Dianne Hackbornc895be72013-03-11 17:48:43 -07003756 } else if (tagName.equals("library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003757 sa = res.obtainAttributes(parser,
Dianne Hackbornc895be72013-03-11 17:48:43 -07003758 com.android.internal.R.styleable.AndroidManifestLibrary);
3759
3760 // Note: don't allow this value to be a reference to a resource
3761 // that may change.
3762 String lname = sa.getNonResourceString(
3763 com.android.internal.R.styleable.AndroidManifestLibrary_name);
3764
3765 sa.recycle();
3766
3767 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003768 lname = lname.intern();
3769 if (!ArrayUtils.contains(owner.libraryNames, lname)) {
Svet Ganov67882122016-12-11 16:36:34 -08003770 owner.libraryNames = ArrayUtils.add(
3771 owner.libraryNames, lname);
Dianne Hackbornc895be72013-03-11 17:48:43 -07003772 }
3773 }
3774
3775 XmlUtils.skipCurrentTag(parser);
3776
Svet Ganov67882122016-12-11 16:36:34 -08003777 } else if (tagName.equals("uses-static-library")) {
3778 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
3779 return false;
3780 }
3781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003782 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003783 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003784 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3785
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003786 // Note: don't allow this value to be a reference to a resource
3787 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003788 String lname = sa.getNonResourceString(
3789 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07003790 boolean req = sa.getBoolean(
3791 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3792 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003793
3794 sa.recycle();
3795
Dianne Hackborn49237342009-08-27 20:08:01 -07003796 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003797 lname = lname.intern();
Dianne Hackborn49237342009-08-27 20:08:01 -07003798 if (req) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003799 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07003800 } else {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003801 owner.usesOptionalLibraries = ArrayUtils.add(
3802 owner.usesOptionalLibraries, lname);
3803 }
3804 }
3805
3806 XmlUtils.skipCurrentTag(parser);
3807
3808 } else if (tagName.equals("uses-package")) {
3809 // Dependencies for app installers; we don't currently try to
3810 // enforce this.
3811 XmlUtils.skipCurrentTag(parser);
3812
3813 } else {
3814 if (!RIGID_PARSER) {
3815 Slog.w(TAG, "Unknown element under <application>: " + tagName
3816 + " at " + mArchiveSourcePath + " "
3817 + parser.getPositionDescription());
3818 XmlUtils.skipCurrentTag(parser);
3819 continue;
3820 } else {
3821 outError[0] = "Bad element under <application>: " + tagName;
3822 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3823 return false;
3824 }
3825 }
3826 }
3827
Bryce Lee22571db2017-07-07 15:54:18 -07003828 // Must be ran after the entire {@link ApplicationInfo} has been fully processed and after
3829 // every activity info has had a chance to set it from its attributes.
3830 setMaxAspectRatio(owner);
3831
Paul Duffin855d7022017-07-10 15:16:07 +01003832 PackageBackwardCompatibility.modifySharedLibraries(owner);
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00003833
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003834 if (hasDomainURLs(owner)) {
3835 owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3836 } else {
3837 owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3838 }
3839
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003840 return true;
3841 }
3842
3843 /**
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003844 * 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 -07003845 */
3846 private static boolean hasDomainURLs(Package pkg) {
3847 if (pkg == null || pkg.activities == null) return false;
3848 final ArrayList<Activity> activities = pkg.activities;
3849 final int countActivities = activities.size();
3850 for (int n=0; n<countActivities; n++) {
3851 Activity activity = activities.get(n);
3852 ArrayList<ActivityIntentInfo> filters = activity.intents;
3853 if (filters == null) continue;
3854 final int countFilters = filters.size();
3855 for (int m=0; m<countFilters; m++) {
3856 ActivityIntentInfo aii = filters.get(m);
3857 if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003858 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003859 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
3860 aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
3861 return true;
3862 }
3863 }
3864 }
3865 return false;
3866 }
3867
3868 /**
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003869 * Parse the {@code application} XML tree at the current parse location in a
3870 * <em>split APK</em> manifest.
3871 * <p>
3872 * Note that split APKs have many more restrictions on what they're capable
3873 * of doing, so many valid features of a base APK have been carefully
3874 * omitted here.
3875 */
Svet Ganov354cd3c2015-12-17 11:35:04 -08003876 private boolean parseSplitApplication(Package owner, Resources res, XmlResourceParser parser,
3877 int flags, int splitIndex, String[] outError)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003878 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003879 TypedArray sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003880 com.android.internal.R.styleable.AndroidManifestApplication);
3881
3882 if (sa.getBoolean(
3883 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
3884 owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
3885 }
3886
Narayan Kamath96c11c52017-08-09 13:07:21 +01003887 final String classLoaderName = sa.getString(
3888 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
3889 if (classLoaderName == null || ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) {
3890 owner.applicationInfo.splitClassLoaderNames[splitIndex] = classLoaderName;
3891 } else {
3892 outError[0] = "Invalid class loader name: " + classLoaderName;
3893 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3894 return false;
3895 }
3896
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003897 final int innerDepth = parser.getDepth();
3898 int type;
3899 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3900 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3901 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3902 continue;
3903 }
3904
Adam Lesinski4e862812016-11-21 16:02:24 -08003905 ComponentInfo parsedComponent = null;
3906
Garrett Boyer52136662017-05-23 13:47:58 -07003907 // IMPORTANT: These must only be cached for a single <application> to avoid components
3908 // getting added to the wrong package.
3909 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003910 String tagName = parser.getName();
3911 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003912 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003913 owner.baseHardwareAccelerated);
3914 if (a == null) {
3915 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3916 return false;
3917 }
3918
3919 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003920 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003921
3922 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003923 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
3924 true, false);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003925 if (a == null) {
3926 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3927 return false;
3928 }
3929
3930 owner.receivers.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003931 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003932
3933 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003934 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003935 if (s == null) {
3936 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3937 return false;
3938 }
3939
3940 owner.services.add(s);
Adam Lesinski4e862812016-11-21 16:02:24 -08003941 parsedComponent = s.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003942
3943 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003944 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003945 if (p == null) {
3946 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3947 return false;
3948 }
3949
3950 owner.providers.add(p);
Adam Lesinski4e862812016-11-21 16:02:24 -08003951 parsedComponent = p.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003952
3953 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003954 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003955 if (a == null) {
3956 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3957 return false;
3958 }
3959
3960 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003961 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003962
3963 } else if (parser.getName().equals("meta-data")) {
3964 // note: application meta-data is stored off to the side, so it can
3965 // remain null in the primary copy (we like to avoid extra copies because
3966 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003967 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003968 outError)) == null) {
3969 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3970 return false;
3971 }
3972
Svet Ganov67882122016-12-11 16:36:34 -08003973 } else if (tagName.equals("uses-static-library")) {
3974 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
3975 return false;
3976 }
3977
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003978 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003979 sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003980 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3981
3982 // Note: don't allow this value to be a reference to a resource
3983 // that may change.
3984 String lname = sa.getNonResourceString(
3985 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
3986 boolean req = sa.getBoolean(
3987 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3988 true);
3989
3990 sa.recycle();
3991
3992 if (lname != null) {
3993 lname = lname.intern();
3994 if (req) {
3995 // Upgrade to treat as stronger constraint
3996 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
3997 owner.usesOptionalLibraries = ArrayUtils.remove(
3998 owner.usesOptionalLibraries, lname);
3999 } else {
4000 // Ignore if someone already defined as required
4001 if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
4002 owner.usesOptionalLibraries = ArrayUtils.add(
4003 owner.usesOptionalLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07004004 }
4005 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004006 }
4007
4008 XmlUtils.skipCurrentTag(parser);
4009
Dianne Hackborncef65ee2010-09-30 18:27:22 -07004010 } else if (tagName.equals("uses-package")) {
4011 // Dependencies for app installers; we don't currently try to
4012 // enforce this.
4013 XmlUtils.skipCurrentTag(parser);
4014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004015 } else {
4016 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004017 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004018 + " at " + mArchiveSourcePath + " "
4019 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004020 XmlUtils.skipCurrentTag(parser);
4021 continue;
4022 } else {
4023 outError[0] = "Bad element under <application>: " + tagName;
4024 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4025 return false;
4026 }
4027 }
Adam Lesinski4e862812016-11-21 16:02:24 -08004028
4029 if (parsedComponent != null && parsedComponent.splitName == null) {
4030 // If the loaded component did not specify a split, inherit the split name
4031 // based on the split it is defined in.
4032 // This is used to later load the correct split when starting this
4033 // component.
4034 parsedComponent.splitName = owner.splitNames[splitIndex];
4035 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004036 }
4037
4038 return true;
4039 }
4040
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004041 private static boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
4042 String[] outError, String tag, TypedArray sa, boolean nameRequired,
4043 int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00004044 // This case can only happen in unit tests where we sometimes need to create fakes
4045 // of various package parser data structures.
4046 if (sa == null) {
4047 outError[0] = tag + " does not contain any attributes";
4048 return false;
4049 }
4050
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004051 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004052 if (name == null) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004053 if (nameRequired) {
4054 outError[0] = tag + " does not specify android:name";
4055 return false;
4056 }
4057 } else {
4058 outInfo.name
4059 = buildClassName(owner.applicationInfo.packageName, name, outError);
4060 if (outInfo.name == null) {
4061 return false;
4062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004063 }
4064
Todd Kennedya83bfca2016-06-03 07:52:17 -07004065 final boolean useRoundIcon =
4066 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
4067 int roundIconVal = useRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004068 if (roundIconVal != 0) {
4069 outInfo.icon = roundIconVal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004070 outInfo.nonLocalizedLabel = null;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004071 } else {
4072 int iconVal = sa.getResourceId(iconRes, 0);
4073 if (iconVal != 0) {
4074 outInfo.icon = iconVal;
4075 outInfo.nonLocalizedLabel = null;
4076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004077 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004078
Adam Powell81cd2e92010-04-21 16:35:18 -07004079 int logoVal = sa.getResourceId(logoRes, 0);
4080 if (logoVal != 0) {
4081 outInfo.logo = logoVal;
4082 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004083
Jose Limaf78e3122014-03-06 12:13:15 -08004084 int bannerVal = sa.getResourceId(bannerRes, 0);
4085 if (bannerVal != 0) {
4086 outInfo.banner = bannerVal;
4087 }
4088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004089 TypedValue v = sa.peekValue(labelRes);
4090 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4091 outInfo.nonLocalizedLabel = v.coerceToString();
4092 }
4093
4094 outInfo.packageName = owner.packageName;
4095
4096 return true;
4097 }
4098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004099 private Activity parseActivity(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004100 XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs,
Romain Guy529b60a2010-08-03 18:05:47 -07004101 boolean receiver, boolean hardwareAccelerated)
4102 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004103 TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104
Garrett Boyer52136662017-05-23 13:47:58 -07004105 if (cachedArgs.mActivityArgs == null) {
4106 cachedArgs.mActivityArgs = new ParseComponentArgs(owner, outError,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004107 R.styleable.AndroidManifestActivity_name,
4108 R.styleable.AndroidManifestActivity_label,
4109 R.styleable.AndroidManifestActivity_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004110 R.styleable.AndroidManifestActivity_roundIcon,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004111 R.styleable.AndroidManifestActivity_logo,
4112 R.styleable.AndroidManifestActivity_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004113 mSeparateProcesses,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004114 R.styleable.AndroidManifestActivity_process,
4115 R.styleable.AndroidManifestActivity_description,
4116 R.styleable.AndroidManifestActivity_enabled);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004117 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004118
Garrett Boyer52136662017-05-23 13:47:58 -07004119 cachedArgs.mActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
4120 cachedArgs.mActivityArgs.sa = sa;
4121 cachedArgs.mActivityArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004122
Garrett Boyer52136662017-05-23 13:47:58 -07004123 Activity a = new Activity(cachedArgs.mActivityArgs, new ActivityInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004124 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004125 sa.recycle();
4126 return null;
4127 }
4128
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004129 boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004130 if (setExported) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004131 a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004132 }
4133
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004134 a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004135
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004136 a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
Adam Powell269248d2011-08-02 10:26:54 -07004137 a.info.applicationInfo.uiOptions);
4138
Adam Powelldd8fab22012-03-22 17:47:27 -07004139 String parentName = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004140 R.styleable.AndroidManifestActivity_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004141 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004142 if (parentName != null) {
4143 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4144 if (outError[0] == null) {
4145 a.info.parentActivityName = parentClassName;
4146 } else {
4147 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
4148 parentName);
4149 outError[0] = null;
4150 }
4151 }
4152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004153 String str;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004154 str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004155 if (str == null) {
4156 a.info.permission = owner.applicationInfo.permission;
4157 } else {
4158 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4159 }
4160
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004161 str = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004162 R.styleable.AndroidManifestActivity_taskAffinity,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004163 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004164 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
4165 owner.applicationInfo.taskAffinity, str, outError);
4166
Todd Kennedye9d0d272017-01-23 06:49:29 -08004167 a.info.splitName =
4168 sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_splitName, 0);
4169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004170 a.info.flags = 0;
4171 if (sa.getBoolean(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004172 R.styleable.AndroidManifestActivity_multiprocess, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
4174 }
4175
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004176 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004177 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
4178 }
4179
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004180 if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004181 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
4182 }
4183
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004184 if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004185 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
4186 }
4187
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004188 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004189 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
4190 }
4191
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004192 if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004193 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
4194 }
4195
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004196 if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004197 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
4198 }
4199
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004200 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004201 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
4202 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
4203 }
4204
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004205 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
Dianne Hackbornffa42482009-09-23 22:20:11 -07004206 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
4207 }
4208
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07004209 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
4210 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
4211 a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Craig Mautner5962b122012-10-05 14:45:52 -07004212 }
4213
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004214 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
Daniel Sandler613dde42010-06-21 13:46:39 -04004215 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
4216 }
Craig Mautner5962b122012-10-05 14:45:52 -07004217
Fyodor Kupolov4f5de342015-08-25 10:08:45 -07004218 if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
4219 a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
Fyodor Kupolov703d1c42015-01-27 11:59:00 -08004220 }
4221
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004222 if (!receiver) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004223 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07004224 hardwareAccelerated)) {
4225 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
4226 }
4227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004228 a.info.launchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004229 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
Craig Mautner2dac0562014-05-06 09:06:44 -07004230 a.info.documentLaunchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004231 R.styleable.AndroidManifestActivity_documentLaunchMode,
Craig Mautner2dac0562014-05-06 09:06:44 -07004232 ActivityInfo.DOCUMENT_LAUNCH_NONE);
Craig Mautnerffcfcaa2014-06-05 09:54:38 -07004233 a.info.maxRecents = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004234 R.styleable.AndroidManifestActivity_maxRecents,
Dianne Hackborn852975d2014-08-22 17:42:43 -07004235 ActivityManager.getDefaultAppRecentsLimitStatic());
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004236 a.info.configChanges = getActivityConfigChanges(
4237 sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004238 sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004239 a.info.softInputMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004240 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
Craig Mautner2dac0562014-05-06 09:06:44 -07004241
Craig Mautner43e52ed2014-06-16 17:18:52 -07004242 a.info.persistableMode = sa.getInteger(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004243 R.styleable.AndroidManifestActivity_persistableMode,
Craig Mautner43e52ed2014-06-16 17:18:52 -07004244 ActivityInfo.PERSIST_ROOT_ONLY);
Craig Mautner2dac0562014-05-06 09:06:44 -07004245
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004246 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004247 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
4248 }
4249
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004250 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004251 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
4252 }
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004253
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004254 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004255 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
4256 }
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004257
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004258 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004259 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
4260 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004261
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004262 a.info.screenOrientation = sa.getInt(
4263 R.styleable.AndroidManifestActivity_screenOrientation,
4264 SCREEN_ORIENTATION_UNSPECIFIED);
Wale Ogunwale6a591362015-10-05 20:18:27 -07004265
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004266 setActivityResizeMode(a.info, sa, owner);
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004267
Winson Chungd3395382016-12-13 11:49:09 -08004268 if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
4269 false)) {
4270 a.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE;
4271 }
4272
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004273 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004274 a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004275 }
Wale Ogunwaleb60692e2015-10-24 12:35:56 -07004276
Bryce Lee22571db2017-07-07 15:54:18 -07004277 if (sa.hasValue(R.styleable.AndroidManifestActivity_maxAspectRatio)
4278 && sa.getType(R.styleable.AndroidManifestActivity_maxAspectRatio)
4279 == TypedValue.TYPE_FLOAT) {
4280 a.setMaxAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_maxAspectRatio,
4281 0 /*default*/));
4282 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004283
Craig Mautner15df08a2015-04-01 12:17:18 -07004284 a.info.lockTaskLaunchMode =
4285 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004286
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004287 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4288 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004289 false);
Ruben Brunkf56c9f42016-04-22 18:20:55 -07004290
4291 a.info.requestedVrComponent =
4292 sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
Robert Carr0f5d7532016-10-17 16:39:17 -07004293
4294 a.info.rotationAnimation =
Robert Carr427ba4f2017-07-17 18:37:06 -07004295 sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, ROTATION_ANIMATION_UNSPECIFIED);
Romain Guy48327452017-01-23 17:03:35 -08004296
4297 a.info.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode,
4298 ActivityInfo.COLOR_MODE_DEFAULT);
chaviw59b98852017-06-13 12:05:44 -07004299
4300 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showWhenLocked, false)) {
4301 a.info.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
4302 }
4303
4304 if (sa.getBoolean(R.styleable.AndroidManifestActivity_turnScreenOn, false)) {
4305 a.info.flags |= ActivityInfo.FLAG_TURN_SCREEN_ON;
4306 }
4307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004308 } else {
4309 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
4310 a.info.configChanges = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004311
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004312 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07004313 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004314 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004315
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004316 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4317 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004318 false);
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004319 }
4320
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004321 if (a.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004322 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004323 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004324 }
4325
Todd Kennedy752fb702017-03-21 16:28:10 -07004326 // can't make this final; we may set it later via meta-data
4327 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08004328 sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004329 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004330 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004331 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004332 }
4333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004334 sa.recycle();
4335
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004336 if (receiver && (owner.applicationInfo.privateFlags
4337 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004338 // A heavy-weight application can not have receives in its main process
4339 // We can do direct compare because we intern all strings.
4340 if (a.info.processName == owner.packageName) {
4341 outError[0] = "Heavy-weight applications can not have receivers in main process";
4342 }
4343 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004344
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004345 if (outError[0] != null) {
4346 return null;
4347 }
4348
4349 int outerDepth = parser.getDepth();
4350 int type;
4351 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4352 && (type != XmlPullParser.END_TAG
4353 || parser.getDepth() > outerDepth)) {
4354 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4355 continue;
4356 }
4357
4358 if (parser.getName().equals("intent-filter")) {
4359 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004360 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4361 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004362 return null;
4363 }
4364 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004365 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004366 + mArchiveSourcePath + " "
4367 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004368 } else {
4369 a.intents.add(intent);
4370 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004371 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004372 final int visibility = visibleToEphemeral
4373 ? IntentFilter.VISIBILITY_EXPLICIT
4374 : !receiver && isImplicitlyExposedIntent(intent)
4375 ? IntentFilter.VISIBILITY_IMPLICIT
4376 : IntentFilter.VISIBILITY_NONE;
4377 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004378 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004379 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4380 }
4381 if (intent.isImplicitlyVisibleToInstantApp()) {
4382 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004383 }
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -07004384 if (LOG_UNSAFE_BROADCASTS && receiver
4385 && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
4386 for (int i = 0; i < intent.countActions(); i++) {
4387 final String action = intent.getAction(i);
4388 if (action == null || !action.startsWith("android.")) continue;
4389 if (!SAFE_BROADCASTS.contains(action)) {
4390 Slog.w(TAG, "Broadcast " + action + " may never be delivered to "
4391 + owner.packageName + " as requested at: "
4392 + parser.getPositionDescription());
4393 }
4394 }
4395 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004396 } else if (!receiver && parser.getName().equals("preferred")) {
4397 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004398 if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/,
4399 intent, outError)) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004400 return null;
4401 }
4402 if (intent.countActions() == 0) {
4403 Slog.w(TAG, "No actions in preferred at "
4404 + mArchiveSourcePath + " "
4405 + parser.getPositionDescription());
4406 } else {
4407 if (owner.preferredActivityFilters == null) {
4408 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
4409 }
4410 owner.preferredActivityFilters.add(intent);
4411 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004412 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004413 final int visibility = visibleToEphemeral
4414 ? IntentFilter.VISIBILITY_EXPLICIT
4415 : !receiver && isImplicitlyExposedIntent(intent)
4416 ? IntentFilter.VISIBILITY_IMPLICIT
4417 : IntentFilter.VISIBILITY_NONE;
4418 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004419 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004420 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4421 }
4422 if (intent.isImplicitlyVisibleToInstantApp()) {
4423 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004425 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004426 if ((a.metaData = parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004427 outError)) == null) {
4428 return null;
4429 }
Todd Kennedy752fb702017-03-21 16:28:10 -07004430 // we don't have an attribute [or it's false], but, we have meta-data
4431 if (!visibleToEphemeral && a.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
4432 visibleToEphemeral = true; // set in case there are more intent filters
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004433 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4434 a.info.flags &= ~ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy752fb702017-03-21 16:28:10 -07004435 owner.visibleToInstantApps = true;
4436 // cycle through any filters already seen
4437 for (int i = a.intents.size() - 1; i >= 0; --i) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004438 a.intents.get(i)
4439 .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
Todd Kennedy752fb702017-03-21 16:28:10 -07004440 }
4441 if (owner.preferredActivityFilters != null) {
4442 for (int i = owner.preferredActivityFilters.size() - 1; i >= 0; --i) {
4443 owner.preferredActivityFilters.get(i)
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004444 .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
Todd Kennedy752fb702017-03-21 16:28:10 -07004445 }
4446 }
4447 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004448 } else if (!receiver && parser.getName().equals("layout")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004449 parseLayout(res, parser, a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004450 } else {
4451 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004452 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004453 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004454 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004455 + " at " + mArchiveSourcePath + " "
4456 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004457 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004458 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004459 + " at " + mArchiveSourcePath + " "
4460 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004461 }
4462 XmlUtils.skipCurrentTag(parser);
4463 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004464 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004465 if (receiver) {
4466 outError[0] = "Bad element under <receiver>: " + parser.getName();
4467 } else {
4468 outError[0] = "Bad element under <activity>: " + parser.getName();
4469 }
4470 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004471 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004472 }
4473 }
4474
4475 if (!setExported) {
4476 a.info.exported = a.intents.size() > 0;
4477 }
4478
4479 return a;
4480 }
4481
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004482 private void setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package owner) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004483 final boolean appExplicitDefault = (owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004484 & (PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE
4485 | PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE)) != 0;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004486
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004487 if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity)
4488 || appExplicitDefault) {
4489 // Activity or app explicitly set if it is resizeable or not;
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004490 final boolean appResizeable = (owner.applicationInfo.privateFlags
4491 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE) != 0;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004492 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity,
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004493 appResizeable)) {
Winson Chungd3395382016-12-13 11:49:09 -08004494 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004495 } else {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004496 aInfo.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004497 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004498 return;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004499 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004500
4501 if ((owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004502 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) != 0) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004503 // The activity or app didn't explicitly set the resizing option, however we want to
4504 // make it resize due to the sdk version it is targeting.
4505 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
4506 return;
4507 }
4508
4509 // resize preference isn't set and target sdk version doesn't support resizing apps by
4510 // default. For the app to be resizeable if it isn't fixed orientation or immersive.
skuhne@google.com322347b2016-12-02 12:54:03 -08004511 if (aInfo.isFixedOrientationPortrait()) {
4512 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
4513 } else if (aInfo.isFixedOrientationLandscape()) {
4514 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
4515 } else if (aInfo.isFixedOrientation()) {
4516 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
4517 } else {
4518 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
4519 }
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004520 }
4521
Bryce Lee22571db2017-07-07 15:54:18 -07004522 /**
4523 * Sets every the max aspect ratio of every child activity that doesn't already have an aspect
4524 * ratio set.
4525 */
4526 private void setMaxAspectRatio(Package owner) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004527 // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater.
4528 // 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 -07004529 float maxAspectRatio = owner.applicationInfo.targetSdkVersion < O
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004530 ? DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0;
Bryce Lee22571db2017-07-07 15:54:18 -07004531
4532 if (owner.applicationInfo.maxAspectRatio != 0) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004533 // Use the application max aspect ration as default if set.
Bryce Lee22571db2017-07-07 15:54:18 -07004534 maxAspectRatio = owner.applicationInfo.maxAspectRatio;
4535 } else if (owner.mAppMetaData != null
4536 && owner.mAppMetaData.containsKey(METADATA_MAX_ASPECT_RATIO)) {
4537 maxAspectRatio = owner.mAppMetaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004538 }
4539
Bryce Lee22571db2017-07-07 15:54:18 -07004540 for (Activity activity : owner.activities) {
4541 // If the max aspect ratio for the activity has already been set, skip.
4542 if (activity.hasMaxAspectRatio()) {
4543 continue;
4544 }
4545
4546 // By default we prefer to use a values defined on the activity directly than values
4547 // defined on the application. We do not check the styled attributes on the activity
4548 // as it would have already been set when we processed the activity. We wait to process
4549 // the meta data here since this method is called at the end of processing the
4550 // application and all meta data is guaranteed.
4551 final float activityAspectRatio = activity.metaData != null
4552 ? activity.metaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio)
4553 : maxAspectRatio;
4554
4555 activity.setMaxAspectRatio(activityAspectRatio);
Wale Ogunwale0cb70ac2017-03-27 09:16:38 -07004556 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004557 }
4558
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004559 /**
4560 * @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml.
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004561 * @param recreateOnConfigChanges The bit mask recreateOnConfigChanges fetched from
4562 * AndroidManifest.xml.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004563 * @hide Exposed for unit testing only.
4564 */
4565 @TestApi
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004566 public static int getActivityConfigChanges(int configChanges, int recreateOnConfigChanges) {
4567 return configChanges | ((~recreateOnConfigChanges) & RECREATE_ON_CONFIG_CHANGES_MASK);
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004568 }
4569
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004570 private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004571 TypedArray sw = res.obtainAttributes(attrs,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004572 com.android.internal.R.styleable.AndroidManifestLayout);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004573 int width = -1;
4574 float widthFraction = -1f;
4575 int height = -1;
4576 float heightFraction = -1f;
4577 final int widthType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004578 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004579 if (widthType == TypedValue.TYPE_FRACTION) {
4580 widthFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004581 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004582 1, 1, -1);
4583 } else if (widthType == TypedValue.TYPE_DIMENSION) {
4584 width = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004585 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004586 -1);
4587 }
4588 final int heightType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004589 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004590 if (heightType == TypedValue.TYPE_FRACTION) {
4591 heightFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004592 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004593 1, 1, -1);
4594 } else if (heightType == TypedValue.TYPE_DIMENSION) {
4595 height = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004596 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004597 -1);
4598 }
4599 int gravity = sw.getInt(
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004600 com.android.internal.R.styleable.AndroidManifestLayout_gravity,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004601 Gravity.CENTER);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004602 int minWidth = sw.getDimensionPixelSize(
4603 com.android.internal.R.styleable.AndroidManifestLayout_minWidth,
Andrii Kulian2e751b82016-03-16 16:59:32 -07004604 -1);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004605 int minHeight = sw.getDimensionPixelSize(
4606 com.android.internal.R.styleable.AndroidManifestLayout_minHeight,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004607 -1);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004608 sw.recycle();
Andrii Kulian2e751b82016-03-16 16:59:32 -07004609 a.info.windowLayout = new ActivityInfo.WindowLayout(width, widthFraction,
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004610 height, heightFraction, gravity, minWidth, minHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004611 }
4612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004613 private Activity parseActivityAlias(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004614 XmlResourceParser parser, int flags, String[] outError,
4615 CachedComponentArgs cachedArgs)
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004616 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004617 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004618 com.android.internal.R.styleable.AndroidManifestActivityAlias);
4619
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004620 String targetActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004621 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
4622 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004623 if (targetActivity == null) {
4624 outError[0] = "<activity-alias> does not specify android:targetActivity";
4625 sa.recycle();
4626 return null;
4627 }
4628
4629 targetActivity = buildClassName(owner.applicationInfo.packageName,
4630 targetActivity, outError);
4631 if (targetActivity == null) {
4632 sa.recycle();
4633 return null;
4634 }
4635
Garrett Boyer52136662017-05-23 13:47:58 -07004636 if (cachedArgs.mActivityAliasArgs == null) {
4637 cachedArgs.mActivityAliasArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004638 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
4639 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
4640 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004641 com.android.internal.R.styleable.AndroidManifestActivityAlias_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004642 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004643 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004644 mSeparateProcesses,
4645 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004646 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004647 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07004648 cachedArgs.mActivityAliasArgs.tag = "<activity-alias>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004649 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004650
Garrett Boyer52136662017-05-23 13:47:58 -07004651 cachedArgs.mActivityAliasArgs.sa = sa;
4652 cachedArgs.mActivityAliasArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004654 Activity target = null;
4655
4656 final int NA = owner.activities.size();
4657 for (int i=0; i<NA; i++) {
4658 Activity t = owner.activities.get(i);
4659 if (targetActivity.equals(t.info.name)) {
4660 target = t;
4661 break;
4662 }
4663 }
4664
4665 if (target == null) {
4666 outError[0] = "<activity-alias> target activity " + targetActivity
4667 + " not found in manifest";
4668 sa.recycle();
4669 return null;
4670 }
4671
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004672 ActivityInfo info = new ActivityInfo();
4673 info.targetActivity = targetActivity;
4674 info.configChanges = target.info.configChanges;
4675 info.flags = target.info.flags;
4676 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07004677 info.logo = target.info.logo;
Jose Limaf78e3122014-03-06 12:13:15 -08004678 info.banner = target.info.banner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004679 info.labelRes = target.info.labelRes;
4680 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
4681 info.launchMode = target.info.launchMode;
Yao Chen597ad3f2015-06-09 16:00:14 -07004682 info.lockTaskLaunchMode = target.info.lockTaskLaunchMode;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004683 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004684 if (info.descriptionRes == 0) {
4685 info.descriptionRes = target.info.descriptionRes;
4686 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004687 info.screenOrientation = target.info.screenOrientation;
4688 info.taskAffinity = target.info.taskAffinity;
4689 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07004690 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07004691 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07004692 info.parentActivityName = target.info.parentActivityName;
Craig Mautner8307ea72014-09-11 15:03:53 -07004693 info.maxRecents = target.info.maxRecents;
Andrii Kulian2e751b82016-03-16 16:59:32 -07004694 info.windowLayout = target.info.windowLayout;
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004695 info.resizeMode = target.info.resizeMode;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004696 info.maxAspectRatio = target.info.maxAspectRatio;
Bryce Lee22571db2017-07-07 15:54:18 -07004697
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004698 info.encryptionAware = info.directBootAware = target.info.directBootAware;
Craig Mautner8307ea72014-09-11 15:03:53 -07004699
Garrett Boyer52136662017-05-23 13:47:58 -07004700 Activity a = new Activity(cachedArgs.mActivityAliasArgs, info);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004701 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004702 sa.recycle();
4703 return null;
4704 }
4705
4706 final boolean setExported = sa.hasValue(
4707 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
4708 if (setExported) {
4709 a.info.exported = sa.getBoolean(
4710 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
4711 }
4712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004713 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004714 str = sa.getNonConfigurationString(
4715 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004716 if (str != null) {
4717 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4718 }
4719
Adam Powelldd8fab22012-03-22 17:47:27 -07004720 String parentName = sa.getNonConfigurationString(
4721 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004722 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004723 if (parentName != null) {
4724 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4725 if (outError[0] == null) {
4726 a.info.parentActivityName = parentClassName;
4727 } else {
4728 Log.e(TAG, "Activity alias " + a.info.name +
4729 " specified invalid parentActivityName " + parentName);
4730 outError[0] = null;
4731 }
4732 }
4733
Chad Brubaker699c7712017-01-20 13:53:42 -08004734 // TODO add visibleToInstantApps attribute to activity alias
Todd Kennedybe0b8892017-02-15 14:13:52 -08004735 final boolean visibleToEphemeral =
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004736 ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004738 sa.recycle();
4739
4740 if (outError[0] != null) {
4741 return null;
4742 }
4743
4744 int outerDepth = parser.getDepth();
4745 int type;
4746 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4747 && (type != XmlPullParser.END_TAG
4748 || parser.getDepth() > outerDepth)) {
4749 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4750 continue;
4751 }
4752
4753 if (parser.getName().equals("intent-filter")) {
4754 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004755 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4756 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004757 return null;
4758 }
4759 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004760 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004761 + mArchiveSourcePath + " "
4762 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004763 } else {
4764 a.intents.add(intent);
4765 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004766 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004767 final int visibility = visibleToEphemeral
4768 ? IntentFilter.VISIBILITY_EXPLICIT
4769 : isImplicitlyExposedIntent(intent)
4770 ? IntentFilter.VISIBILITY_IMPLICIT
4771 : IntentFilter.VISIBILITY_NONE;
4772 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004773 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004774 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4775 }
4776 if (intent.isImplicitlyVisibleToInstantApp()) {
4777 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004778 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004779 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004780 if ((a.metaData=parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004781 outError)) == null) {
4782 return null;
4783 }
4784 } else {
4785 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004786 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004787 + " at " + mArchiveSourcePath + " "
4788 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004789 XmlUtils.skipCurrentTag(parser);
4790 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004791 } else {
4792 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
4793 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004795 }
4796 }
4797
4798 if (!setExported) {
4799 a.info.exported = a.intents.size() > 0;
4800 }
4801
4802 return a;
4803 }
4804
4805 private Provider parseProvider(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004806 XmlResourceParser parser, int flags, String[] outError,
4807 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004808 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004809 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004810 com.android.internal.R.styleable.AndroidManifestProvider);
4811
Garrett Boyer52136662017-05-23 13:47:58 -07004812 if (cachedArgs.mProviderArgs == null) {
4813 cachedArgs.mProviderArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004814 com.android.internal.R.styleable.AndroidManifestProvider_name,
4815 com.android.internal.R.styleable.AndroidManifestProvider_label,
4816 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004817 com.android.internal.R.styleable.AndroidManifestProvider_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004818 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004819 com.android.internal.R.styleable.AndroidManifestProvider_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004820 mSeparateProcesses,
4821 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004822 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004823 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07004824 cachedArgs.mProviderArgs.tag = "<provider>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004825 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004826
Garrett Boyer52136662017-05-23 13:47:58 -07004827 cachedArgs.mProviderArgs.sa = sa;
4828 cachedArgs.mProviderArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004829
Garrett Boyer52136662017-05-23 13:47:58 -07004830 Provider p = new Provider(cachedArgs.mProviderArgs, new ProviderInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004831 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004832 sa.recycle();
4833 return null;
4834 }
4835
Nick Kralevichf097b162012-07-28 12:43:48 -07004836 boolean providerExportedDefault = false;
4837
4838 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
4839 // For compatibility, applications targeting API level 16 or lower
4840 // should have their content providers exported by default, unless they
4841 // specify otherwise.
4842 providerExportedDefault = true;
4843 }
4844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07004846 com.android.internal.R.styleable.AndroidManifestProvider_exported,
4847 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004848
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004849 String cpname = sa.getNonConfigurationString(
4850 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004851
4852 p.info.isSyncable = sa.getBoolean(
4853 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
4854 false);
4855
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004856 String permission = sa.getNonConfigurationString(
4857 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
4858 String str = sa.getNonConfigurationString(
4859 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004860 if (str == null) {
4861 str = permission;
4862 }
4863 if (str == null) {
4864 p.info.readPermission = owner.applicationInfo.permission;
4865 } else {
4866 p.info.readPermission =
4867 str.length() > 0 ? str.toString().intern() : null;
4868 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004869 str = sa.getNonConfigurationString(
4870 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004871 if (str == null) {
4872 str = permission;
4873 }
4874 if (str == null) {
4875 p.info.writePermission = owner.applicationInfo.permission;
4876 } else {
4877 p.info.writePermission =
4878 str.length() > 0 ? str.toString().intern() : null;
4879 }
4880
4881 p.info.grantUriPermissions = sa.getBoolean(
4882 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
4883 false);
4884
4885 p.info.multiprocess = sa.getBoolean(
4886 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
4887 false);
4888
4889 p.info.initOrder = sa.getInt(
4890 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
4891 0);
4892
Todd Kennedye9d0d272017-01-23 06:49:29 -08004893 p.info.splitName =
4894 sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_splitName, 0);
4895
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004896 p.info.flags = 0;
4897
4898 if (sa.getBoolean(
4899 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
4900 false)) {
4901 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004902 }
4903
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004904 p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
4905 R.styleable.AndroidManifestProvider_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004906 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004907 if (p.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004908 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004909 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004910 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004911
Todd Kennedybe0b8892017-02-15 14:13:52 -08004912 final boolean visibleToEphemeral =
4913 sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004914 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004915 p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004916 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004917 }
4918
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004919 sa.recycle();
4920
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004921 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
4922 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004923 // A heavy-weight application can not have providers in its main process
4924 // We can do direct compare because we intern all strings.
4925 if (p.info.processName == owner.packageName) {
4926 outError[0] = "Heavy-weight applications can not have providers in main process";
4927 return null;
4928 }
4929 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004930
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004931 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07004932 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004933 return null;
4934 }
Dianne Hackborn1bc177c2014-12-03 10:20:30 -08004935 if (cpname.length() <= 0) {
4936 outError[0] = "<provider> has empty authorities attribute";
4937 return null;
4938 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 p.info.authority = cpname.intern();
4940
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004941 if (!parseProviderTags(
Todd Kennedy752fb702017-03-21 16:28:10 -07004942 res, parser, visibleToEphemeral, owner, p, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004943 return null;
4944 }
4945
4946 return p;
4947 }
4948
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004949 private boolean parseProviderTags(Resources res, XmlResourceParser parser,
Todd Kennedy752fb702017-03-21 16:28:10 -07004950 boolean visibleToEphemeral, Package owner, Provider outInfo, String[] outError)
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004951 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952 int outerDepth = parser.getDepth();
4953 int type;
4954 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4955 && (type != XmlPullParser.END_TAG
4956 || parser.getDepth() > outerDepth)) {
4957 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4958 continue;
4959 }
4960
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004961 if (parser.getName().equals("intent-filter")) {
4962 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004963 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
4964 intent, outError)) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004965 return false;
4966 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004967 if (visibleToEphemeral) {
4968 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
4969 outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004970 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004971 outInfo.intents.add(intent);
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004972
4973 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004974 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004975 outInfo.metaData, outError)) == null) {
4976 return false;
4977 }
Todd Kennedy752fb702017-03-21 16:28:10 -07004978 // we don't have an attribute [or it's false], but, we have meta-data
4979 if (!visibleToEphemeral && outInfo.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
4980 visibleToEphemeral = true; // set in case there are more intent filters
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004981 outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy752fb702017-03-21 16:28:10 -07004982 owner.visibleToInstantApps = true;
4983 // cycle through any filters already seen
4984 for (int i = outInfo.intents.size() - 1; i >= 0; --i) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004985 outInfo.intents.get(i)
4986 .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
Todd Kennedy752fb702017-03-21 16:28:10 -07004987 }
4988 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004989
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004990 } else if (parser.getName().equals("grant-uri-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004991 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004992 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
4993
4994 PatternMatcher pa = null;
4995
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004996 String str = sa.getNonConfigurationString(
4997 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004998 if (str != null) {
4999 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
5000 }
5001
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005002 str = sa.getNonConfigurationString(
5003 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005004 if (str != null) {
5005 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
5006 }
5007
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005008 str = sa.getNonConfigurationString(
5009 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005010 if (str != null) {
5011 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5012 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005014 sa.recycle();
5015
5016 if (pa != null) {
5017 if (outInfo.info.uriPermissionPatterns == null) {
5018 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
5019 outInfo.info.uriPermissionPatterns[0] = pa;
5020 } else {
5021 final int N = outInfo.info.uriPermissionPatterns.length;
5022 PatternMatcher[] newp = new PatternMatcher[N+1];
5023 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
5024 newp[N] = pa;
5025 outInfo.info.uriPermissionPatterns = newp;
5026 }
5027 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005028 } else {
5029 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005030 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005031 + parser.getName() + " at " + mArchiveSourcePath + " "
5032 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005033 XmlUtils.skipCurrentTag(parser);
5034 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005035 } else {
5036 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5037 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005038 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005039 }
5040 XmlUtils.skipCurrentTag(parser);
5041
5042 } else if (parser.getName().equals("path-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005043 TypedArray sa = res.obtainAttributes(parser,
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005044 com.android.internal.R.styleable.AndroidManifestPathPermission);
5045
5046 PathPermission pa = null;
5047
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005048 String permission = sa.getNonConfigurationString(
5049 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
5050 String readPermission = sa.getNonConfigurationString(
5051 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005052 if (readPermission == null) {
5053 readPermission = permission;
5054 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005055 String writePermission = sa.getNonConfigurationString(
5056 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005057 if (writePermission == null) {
5058 writePermission = permission;
5059 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005060
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005061 boolean havePerm = false;
5062 if (readPermission != null) {
5063 readPermission = readPermission.intern();
5064 havePerm = true;
5065 }
5066 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00005067 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005068 havePerm = true;
5069 }
5070
5071 if (!havePerm) {
5072 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005073 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005074 + parser.getName() + " at " + mArchiveSourcePath + " "
5075 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005076 XmlUtils.skipCurrentTag(parser);
5077 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005078 } else {
5079 outError[0] = "No readPermission or writePermssion for <path-permission>";
5080 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005081 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005082 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005083
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005084 String path = sa.getNonConfigurationString(
5085 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005086 if (path != null) {
5087 pa = new PathPermission(path,
5088 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
5089 }
5090
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005091 path = sa.getNonConfigurationString(
5092 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005093 if (path != null) {
5094 pa = new PathPermission(path,
5095 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
5096 }
5097
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005098 path = sa.getNonConfigurationString(
5099 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005100 if (path != null) {
5101 pa = new PathPermission(path,
5102 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
5103 }
5104
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005105 path = sa.getNonConfigurationString(
5106 com.android.internal.R.styleable.AndroidManifestPathPermission_pathAdvancedPattern, 0);
5107 if (path != null) {
5108 pa = new PathPermission(path,
5109 PatternMatcher.PATTERN_ADVANCED_GLOB, readPermission, writePermission);
5110 }
5111
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005112 sa.recycle();
5113
5114 if (pa != null) {
5115 if (outInfo.info.pathPermissions == null) {
5116 outInfo.info.pathPermissions = new PathPermission[1];
5117 outInfo.info.pathPermissions[0] = pa;
5118 } else {
5119 final int N = outInfo.info.pathPermissions.length;
5120 PathPermission[] newp = new PathPermission[N+1];
5121 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
5122 newp[N] = pa;
5123 outInfo.info.pathPermissions = newp;
5124 }
5125 } else {
5126 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005127 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005128 + parser.getName() + " at " + mArchiveSourcePath + " "
5129 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005130 XmlUtils.skipCurrentTag(parser);
5131 continue;
5132 }
5133 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5134 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005135 }
5136 XmlUtils.skipCurrentTag(parser);
5137
5138 } else {
5139 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005140 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005141 + parser.getName() + " at " + mArchiveSourcePath + " "
5142 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005143 XmlUtils.skipCurrentTag(parser);
5144 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005145 } else {
5146 outError[0] = "Bad element under <provider>: " + parser.getName();
5147 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005148 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005149 }
5150 }
5151 return true;
5152 }
5153
5154 private Service parseService(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07005155 XmlResourceParser parser, int flags, String[] outError,
5156 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005157 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005158 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005159 com.android.internal.R.styleable.AndroidManifestService);
5160
Garrett Boyer52136662017-05-23 13:47:58 -07005161 if (cachedArgs.mServiceArgs == null) {
5162 cachedArgs.mServiceArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005163 com.android.internal.R.styleable.AndroidManifestService_name,
5164 com.android.internal.R.styleable.AndroidManifestService_label,
5165 com.android.internal.R.styleable.AndroidManifestService_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005166 com.android.internal.R.styleable.AndroidManifestService_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07005167 com.android.internal.R.styleable.AndroidManifestService_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08005168 com.android.internal.R.styleable.AndroidManifestService_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005169 mSeparateProcesses,
5170 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005171 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005172 com.android.internal.R.styleable.AndroidManifestService_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07005173 cachedArgs.mServiceArgs.tag = "<service>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005174 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005175
Garrett Boyer52136662017-05-23 13:47:58 -07005176 cachedArgs.mServiceArgs.sa = sa;
5177 cachedArgs.mServiceArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005178
Garrett Boyer52136662017-05-23 13:47:58 -07005179 Service s = new Service(cachedArgs.mServiceArgs, new ServiceInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005180 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005181 sa.recycle();
5182 return null;
5183 }
5184
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005185 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005186 com.android.internal.R.styleable.AndroidManifestService_exported);
5187 if (setExported) {
5188 s.info.exported = sa.getBoolean(
5189 com.android.internal.R.styleable.AndroidManifestService_exported, false);
5190 }
5191
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005192 String str = sa.getNonConfigurationString(
5193 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005194 if (str == null) {
5195 s.info.permission = owner.applicationInfo.permission;
5196 } else {
5197 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
5198 }
5199
Todd Kennedye9d0d272017-01-23 06:49:29 -08005200 s.info.splitName =
5201 sa.getNonConfigurationString(R.styleable.AndroidManifestService_splitName, 0);
5202
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005203 s.info.flags = 0;
5204 if (sa.getBoolean(
5205 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
5206 false)) {
5207 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
5208 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08005209 if (sa.getBoolean(
5210 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
5211 false)) {
5212 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
5213 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005214 if (sa.getBoolean(
Robert Sesekb9a86662015-12-09 16:22:45 -05005215 com.android.internal.R.styleable.AndroidManifestService_externalService,
5216 false)) {
5217 s.info.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE;
5218 }
5219 if (sa.getBoolean(
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005220 com.android.internal.R.styleable.AndroidManifestService_singleUser,
5221 false)) {
5222 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005223 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005224
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005225 s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
5226 R.styleable.AndroidManifestService_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07005227 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005228 if (s.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07005229 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005230 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07005231 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08005232
Todd Kennedy752fb702017-03-21 16:28:10 -07005233 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08005234 sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005235 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005236 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005237 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005238 }
5239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005240 sa.recycle();
5241
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005242 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
5243 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005244 // A heavy-weight application can not have services in its main process
5245 // We can do direct compare because we intern all strings.
5246 if (s.info.processName == owner.packageName) {
5247 outError[0] = "Heavy-weight applications can not have services in main process";
5248 return null;
5249 }
5250 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005251
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005252 int outerDepth = parser.getDepth();
5253 int type;
5254 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5255 && (type != XmlPullParser.END_TAG
5256 || parser.getDepth() > outerDepth)) {
5257 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5258 continue;
5259 }
5260
5261 if (parser.getName().equals("intent-filter")) {
5262 ServiceIntentInfo intent = new ServiceIntentInfo(s);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005263 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
5264 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005265 return null;
5266 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005267 if (visibleToEphemeral) {
5268 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
5269 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005270 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005271 s.intents.add(intent);
5272 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005273 if ((s.metaData=parseMetaData(res, parser, s.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005274 outError)) == null) {
5275 return null;
5276 }
Todd Kennedy752fb702017-03-21 16:28:10 -07005277 // we don't have an attribute [or it's false], but, we have meta-data
5278 if (!visibleToEphemeral && s.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
5279 visibleToEphemeral = true; // set in case there are more intent filters
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005280 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy752fb702017-03-21 16:28:10 -07005281 owner.visibleToInstantApps = true;
5282 // cycle through any filters already seen
5283 for (int i = s.intents.size() - 1; i >= 0; --i) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005284 s.intents.get(i)
5285 .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
Todd Kennedy752fb702017-03-21 16:28:10 -07005286 }
5287 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005288 } else {
5289 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005290 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005291 + parser.getName() + " at " + mArchiveSourcePath + " "
5292 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005293 XmlUtils.skipCurrentTag(parser);
5294 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005295 } else {
5296 outError[0] = "Bad element under <service>: " + parser.getName();
5297 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005298 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005299 }
5300 }
5301
5302 if (!setExported) {
5303 s.info.exported = s.intents.size() > 0;
5304 }
5305
5306 return s;
5307 }
5308
Chad Brubaker49414832017-04-13 16:13:23 -07005309 private boolean isImplicitlyExposedIntent(IntentInfo intent) {
5310 return intent.hasCategory(Intent.CATEGORY_BROWSABLE)
5311 || intent.hasAction(Intent.ACTION_SEND)
5312 || intent.hasAction(Intent.ACTION_SENDTO)
5313 || intent.hasAction(Intent.ACTION_SEND_MULTIPLE);
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005314 }
5315
Svet Ganov354cd3c2015-12-17 11:35:04 -08005316 private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag,
5317 Component<?> outInfo, String[] outError) throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005318 int outerDepth = parser.getDepth();
5319 int type;
5320 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5321 && (type != XmlPullParser.END_TAG
5322 || parser.getDepth() > outerDepth)) {
5323 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5324 continue;
5325 }
5326
5327 if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005328 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005329 outInfo.metaData, outError)) == null) {
5330 return false;
5331 }
5332 } else {
5333 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005334 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005335 + parser.getName() + " at " + mArchiveSourcePath + " "
5336 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005337 XmlUtils.skipCurrentTag(parser);
5338 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005339 } else {
5340 outError[0] = "Bad element under " + tag + ": " + parser.getName();
5341 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005342 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005343 }
5344 }
5345 return true;
5346 }
5347
5348 private Bundle parseMetaData(Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08005349 XmlResourceParser parser, Bundle data, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005350 throws XmlPullParserException, IOException {
5351
Svet Ganov354cd3c2015-12-17 11:35:04 -08005352 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005353 com.android.internal.R.styleable.AndroidManifestMetaData);
5354
5355 if (data == null) {
5356 data = new Bundle();
5357 }
5358
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005359 String name = sa.getNonConfigurationString(
5360 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005361 if (name == null) {
5362 outError[0] = "<meta-data> requires an android:name attribute";
5363 sa.recycle();
5364 return null;
5365 }
5366
Dianne Hackborn854060af2009-07-09 18:14:31 -07005367 name = name.intern();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005369 TypedValue v = sa.peekValue(
5370 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
5371 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005372 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005373 data.putInt(name, v.resourceId);
5374 } else {
5375 v = sa.peekValue(
5376 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07005377 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005378 if (v != null) {
5379 if (v.type == TypedValue.TYPE_STRING) {
5380 CharSequence cs = v.coerceToString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00005381 data.putString(name, cs != null ? cs.toString() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005382 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
5383 data.putBoolean(name, v.data != 0);
5384 } else if (v.type >= TypedValue.TYPE_FIRST_INT
5385 && v.type <= TypedValue.TYPE_LAST_INT) {
5386 data.putInt(name, v.data);
5387 } else if (v.type == TypedValue.TYPE_FLOAT) {
5388 data.putFloat(name, v.getFloat());
5389 } else {
5390 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005391 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005392 + parser.getName() + " at " + mArchiveSourcePath + " "
5393 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005394 } else {
5395 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
5396 data = null;
5397 }
5398 }
5399 } else {
5400 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
5401 data = null;
5402 }
5403 }
5404
5405 sa.recycle();
5406
5407 XmlUtils.skipCurrentTag(parser);
5408
5409 return data;
5410 }
5411
Adam Lesinski4e862812016-11-21 16:02:24 -08005412 private static VerifierInfo parseVerifier(AttributeSet attrs) {
5413 String packageName = null;
5414 String encodedPublicKey = null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005415
Adam Lesinski4e862812016-11-21 16:02:24 -08005416 final int attrCount = attrs.getAttributeCount();
5417 for (int i = 0; i < attrCount; i++) {
5418 final int attrResId = attrs.getAttributeNameResource(i);
5419 switch (attrResId) {
5420 case com.android.internal.R.attr.name:
5421 packageName = attrs.getAttributeValue(i);
5422 break;
Kenny Root05ca4c92011-09-15 10:36:25 -07005423
Adam Lesinski4e862812016-11-21 16:02:24 -08005424 case com.android.internal.R.attr.publicKey:
5425 encodedPublicKey = attrs.getAttributeValue(i);
5426 break;
5427 }
5428 }
Kenny Root05ca4c92011-09-15 10:36:25 -07005429
5430 if (packageName == null || packageName.length() == 0) {
5431 Slog.i(TAG, "verifier package name was null; skipping");
5432 return null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005433 }
5434
Christopher Tate30147332014-04-15 12:57:47 -07005435 final PublicKey publicKey = parsePublicKey(encodedPublicKey);
5436 if (publicKey == null) {
5437 Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
5438 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -08005439 }
5440
Christopher Tate30147332014-04-15 12:57:47 -07005441 return new VerifierInfo(packageName, publicKey);
Geremy Condraf1bcca82013-01-07 22:35:24 -08005442 }
5443
Christopher Tate30147332014-04-15 12:57:47 -07005444 public static final PublicKey parsePublicKey(final String encodedPublicKey) {
5445 if (encodedPublicKey == null) {
dcashman1616f302015-05-29 14:47:23 -07005446 Slog.w(TAG, "Could not parse null public key");
Christopher Tate30147332014-04-15 12:57:47 -07005447 return null;
5448 }
5449
Kenny Root05ca4c92011-09-15 10:36:25 -07005450 EncodedKeySpec keySpec;
5451 try {
5452 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
5453 keySpec = new X509EncodedKeySpec(encoded);
5454 } catch (IllegalArgumentException e) {
dcashman1616f302015-05-29 14:47:23 -07005455 Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07005456 return null;
5457 }
5458
5459 /* First try the key as an RSA key. */
5460 try {
5461 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005462 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005463 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005464 Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005465 } catch (InvalidKeySpecException e) {
5466 // Not a RSA public key.
5467 }
5468
dcashman1616f302015-05-29 14:47:23 -07005469 /* Now try it as a ECDSA key. */
5470 try {
5471 final KeyFactory keyFactory = KeyFactory.getInstance("EC");
5472 return keyFactory.generatePublic(keySpec);
5473 } catch (NoSuchAlgorithmException e) {
5474 Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build");
5475 } catch (InvalidKeySpecException e) {
5476 // Not a ECDSA public key.
5477 }
5478
Kenny Root05ca4c92011-09-15 10:36:25 -07005479 /* Now try it as a DSA key. */
5480 try {
5481 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005482 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005483 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005484 Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005485 } catch (InvalidKeySpecException e) {
5486 // Not a DSA public key.
5487 }
5488
dcashman1616f302015-05-29 14:47:23 -07005489 /* Not a supported key type */
Kenny Root05ca4c92011-09-15 10:36:25 -07005490 return null;
5491 }
5492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005493 private static final String ANDROID_RESOURCES
5494 = "http://schemas.android.com/apk/res/android";
5495
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005496 private boolean parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs,
5497 boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
5498 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005499
Svet Ganov354cd3c2015-12-17 11:35:04 -08005500 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005501 com.android.internal.R.styleable.AndroidManifestIntentFilter);
5502
5503 int priority = sa.getInt(
5504 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005505 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08005506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005507 TypedValue v = sa.peekValue(
5508 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
5509 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
5510 outInfo.nonLocalizedLabel = v.coerceToString();
5511 }
5512
Todd Kennedya83bfca2016-06-03 07:52:17 -07005513 final boolean useRoundIcon =
5514 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
5515 int roundIconVal = useRoundIcon ? sa.getResourceId(
5516 com.android.internal.R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0;
5517 if (roundIconVal != 0) {
5518 outInfo.icon = roundIconVal;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005519 } else {
5520 outInfo.icon = sa.getResourceId(
5521 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
5522 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005523
Adam Powell81cd2e92010-04-21 16:35:18 -07005524 outInfo.logo = sa.getResourceId(
5525 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005526
Jose Limaf78e3122014-03-06 12:13:15 -08005527 outInfo.banner = sa.getResourceId(
5528 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
5529
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08005530 if (allowAutoVerify) {
5531 outInfo.setAutoVerify(sa.getBoolean(
5532 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
5533 false));
5534 }
5535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005536 sa.recycle();
5537
5538 int outerDepth = parser.getDepth();
5539 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07005540 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
5541 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
5542 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005543 continue;
5544 }
5545
5546 String nodeName = parser.getName();
5547 if (nodeName.equals("action")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005548 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005549 ANDROID_RESOURCES, "name");
5550 if (value == null || value == "") {
5551 outError[0] = "No value supplied for <android:name>";
5552 return false;
5553 }
5554 XmlUtils.skipCurrentTag(parser);
5555
5556 outInfo.addAction(value);
5557 } else if (nodeName.equals("category")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005558 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005559 ANDROID_RESOURCES, "name");
5560 if (value == null || value == "") {
5561 outError[0] = "No value supplied for <android:name>";
5562 return false;
5563 }
5564 XmlUtils.skipCurrentTag(parser);
5565
5566 outInfo.addCategory(value);
5567
5568 } else if (nodeName.equals("data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005569 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005570 com.android.internal.R.styleable.AndroidManifestData);
5571
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005572 String str = sa.getNonConfigurationString(
5573 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005574 if (str != null) {
5575 try {
5576 outInfo.addDataType(str);
5577 } catch (IntentFilter.MalformedMimeTypeException e) {
5578 outError[0] = e.toString();
5579 sa.recycle();
5580 return false;
5581 }
5582 }
5583
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005584 str = sa.getNonConfigurationString(
5585 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005586 if (str != null) {
5587 outInfo.addDataScheme(str);
5588 }
5589
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005590 str = sa.getNonConfigurationString(
5591 com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
5592 if (str != null) {
5593 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
5594 }
5595
5596 str = sa.getNonConfigurationString(
5597 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
5598 if (str != null) {
5599 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
5600 }
5601
5602 str = sa.getNonConfigurationString(
5603 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
5604 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005605 if (!allowGlobs) {
5606 outError[0] = "sspPattern not allowed here; ssp must be literal";
5607 return false;
5608 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005609 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5610 }
5611
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005612 String host = sa.getNonConfigurationString(
5613 com.android.internal.R.styleable.AndroidManifestData_host, 0);
5614 String port = sa.getNonConfigurationString(
5615 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005616 if (host != null) {
5617 outInfo.addDataAuthority(host, port);
5618 }
5619
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005620 str = sa.getNonConfigurationString(
5621 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005622 if (str != null) {
5623 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
5624 }
5625
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005626 str = sa.getNonConfigurationString(
5627 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005628 if (str != null) {
5629 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
5630 }
5631
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005632 str = sa.getNonConfigurationString(
5633 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005634 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005635 if (!allowGlobs) {
5636 outError[0] = "pathPattern not allowed here; path must be literal";
5637 return false;
5638 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005639 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5640 }
5641
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005642 str = sa.getNonConfigurationString(
5643 com.android.internal.R.styleable.AndroidManifestData_pathAdvancedPattern, 0);
5644 if (str != null) {
5645 if (!allowGlobs) {
5646 outError[0] = "pathAdvancedPattern not allowed here; path must be literal";
5647 return false;
5648 }
5649 outInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB);
5650 }
5651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005652 sa.recycle();
5653 XmlUtils.skipCurrentTag(parser);
5654 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005655 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005656 + parser.getName() + " at " + mArchiveSourcePath + " "
5657 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005658 XmlUtils.skipCurrentTag(parser);
5659 } else {
5660 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
5661 return false;
5662 }
5663 }
5664
5665 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07005666
5667 if (DEBUG_PARSER) {
5668 final StringBuilder cats = new StringBuilder("Intent d=");
5669 cats.append(outInfo.hasDefault);
5670 cats.append(", cat=");
5671
5672 final Iterator<String> it = outInfo.categoriesIterator();
5673 if (it != null) {
5674 while (it.hasNext()) {
5675 cats.append(' ');
5676 cats.append(it.next());
5677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005678 }
Kenny Rootd2d29252011-08-08 11:27:57 -07005679 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005680 }
5681
5682 return true;
5683 }
5684
Patrick Baumann47117fc2017-12-19 10:17:21 -08005685 /** A container for signing-related data of an application package. */
5686 public static final class SigningDetails implements Parcelable {
5687
5688 @IntDef({SigningDetails.SignatureSchemeVersion.UNKNOWN,
5689 SigningDetails.SignatureSchemeVersion.JAR,
5690 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2,
5691 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3})
5692 public @interface SignatureSchemeVersion {
5693 int UNKNOWN = 0;
5694 int JAR = 1;
5695 int SIGNING_BLOCK_V2 = 2;
5696 int SIGNING_BLOCK_V3 = 3;
5697 }
5698
5699 @Nullable
5700 public final Signature[] signatures;
5701 @SignatureSchemeVersion
5702 public final int signatureSchemeVersion;
5703 @Nullable
5704 public final ArraySet<PublicKey> publicKeys;
5705
Daniel Cashman77029c52018-01-18 16:19:29 -08005706 /**
5707 * Collection of {@code Signature} objects, each of which is formed from a former signing
5708 * certificate of this APK before it was changed by signing certificate rotation.
5709 */
5710 @Nullable
5711 public final Signature[] pastSigningCertificates;
5712
5713 /**
5714 * Flags for the {@code pastSigningCertificates} collection, which indicate the capabilities
5715 * the including APK wishes to grant to its past signing certificates.
5716 */
5717 @Nullable
5718 public final int[] pastSigningCertificatesFlags;
5719
Patrick Baumann47117fc2017-12-19 10:17:21 -08005720 /** A representation of unknown signing details. Use instead of null. */
5721 public static final SigningDetails UNKNOWN =
Daniel Cashman77029c52018-01-18 16:19:29 -08005722 new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null, null, null);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005723
5724 @VisibleForTesting
5725 public SigningDetails(Signature[] signatures,
5726 @SignatureSchemeVersion int signatureSchemeVersion,
Daniel Cashman77029c52018-01-18 16:19:29 -08005727 ArraySet<PublicKey> keys, Signature[] pastSigningCertificates,
5728 int[] pastSigningCertificatesFlags) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08005729 this.signatures = signatures;
5730 this.signatureSchemeVersion = signatureSchemeVersion;
5731 this.publicKeys = keys;
Daniel Cashman77029c52018-01-18 16:19:29 -08005732 this.pastSigningCertificates = pastSigningCertificates;
5733 this.pastSigningCertificatesFlags = pastSigningCertificatesFlags;
5734 }
5735
5736 public SigningDetails(Signature[] signatures,
5737 @SignatureSchemeVersion int signatureSchemeVersion,
5738 Signature[] pastSigningCertificates, int[] pastSigningCertificatesFlags)
5739 throws CertificateException {
5740 this(signatures, signatureSchemeVersion, toSigningKeys(signatures),
5741 pastSigningCertificates, pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005742 }
5743
5744 public SigningDetails(Signature[] signatures,
5745 @SignatureSchemeVersion int signatureSchemeVersion)
5746 throws CertificateException {
Daniel Cashman77029c52018-01-18 16:19:29 -08005747 this(signatures, signatureSchemeVersion,
5748 null, null);
5749 }
5750
5751 public SigningDetails(SigningDetails orig) {
5752 if (orig != null) {
5753 if (orig.signatures != null) {
5754 this.signatures = orig.signatures.clone();
5755 } else {
5756 this.signatures = null;
5757 }
5758 this.signatureSchemeVersion = orig.signatureSchemeVersion;
5759 this.publicKeys = new ArraySet<>(orig.publicKeys);
5760 if (orig.pastSigningCertificates != null) {
5761 this.pastSigningCertificates = orig.pastSigningCertificates.clone();
5762 this.pastSigningCertificatesFlags = orig.pastSigningCertificatesFlags.clone();
5763 } else {
5764 this.pastSigningCertificates = null;
5765 this.pastSigningCertificatesFlags = null;
5766 }
5767 } else {
5768 this.signatures = null;
5769 this.signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
5770 this.publicKeys = null;
5771 this.pastSigningCertificates = null;
5772 this.pastSigningCertificatesFlags = null;
5773 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08005774 }
5775
5776 /** Returns true if the signing details have one or more signatures. */
5777 public boolean hasSignatures() {
5778 return signatures != null && signatures.length > 0;
5779 }
5780
Daniel Cashman5cdda342018-01-19 07:22:52 -08005781 /** Returns true if the signing details have past signing certificates. */
5782 public boolean hasPastSigningCertificates() {
5783 return pastSigningCertificates != null && pastSigningCertificates.length > 0;
5784 }
5785
Patrick Baumann47117fc2017-12-19 10:17:21 -08005786 /** Returns true if the signatures in this and other match exactly. */
5787 public boolean signaturesMatchExactly(SigningDetails other) {
5788 return Signature.areExactMatch(this.signatures, other.signatures);
5789 }
5790
5791 @Override
5792 public int describeContents() {
5793 return 0;
5794 }
5795
5796 @Override
5797 public void writeToParcel(Parcel dest, int flags) {
5798 boolean isUnknown = UNKNOWN == this;
5799 dest.writeBoolean(isUnknown);
5800 if (isUnknown) {
5801 return;
5802 }
5803 dest.writeTypedArray(this.signatures, flags);
5804 dest.writeInt(this.signatureSchemeVersion);
5805 dest.writeArraySet(this.publicKeys);
Daniel Cashman77029c52018-01-18 16:19:29 -08005806 dest.writeTypedArray(this.pastSigningCertificates, flags);
5807 dest.writeIntArray(this.pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005808 }
5809
5810 protected SigningDetails(Parcel in) {
5811 final ClassLoader boot = Object.class.getClassLoader();
5812 this.signatures = in.createTypedArray(Signature.CREATOR);
5813 this.signatureSchemeVersion = in.readInt();
5814 this.publicKeys = (ArraySet<PublicKey>) in.readArraySet(boot);
Daniel Cashman77029c52018-01-18 16:19:29 -08005815 this.pastSigningCertificates = in.createTypedArray(Signature.CREATOR);
5816 this.pastSigningCertificatesFlags = in.createIntArray();
Patrick Baumann47117fc2017-12-19 10:17:21 -08005817 }
5818
5819 public static final Creator<SigningDetails> CREATOR = new Creator<SigningDetails>() {
5820 @Override
5821 public SigningDetails createFromParcel(Parcel source) {
5822 if (source.readBoolean()) {
5823 return UNKNOWN;
5824 }
5825 return new SigningDetails(source);
5826 }
5827
5828 @Override
5829 public SigningDetails[] newArray(int size) {
5830 return new SigningDetails[size];
5831 }
5832 };
5833
5834 @Override
5835 public boolean equals(Object o) {
5836 if (this == o) return true;
5837 if (!(o instanceof SigningDetails)) return false;
5838
5839 SigningDetails that = (SigningDetails) o;
5840
5841 if (signatureSchemeVersion != that.signatureSchemeVersion) return false;
5842 if (!Signature.areExactMatch(signatures, that.signatures)) return false;
Daniel Cashman77029c52018-01-18 16:19:29 -08005843 if (publicKeys != null) {
5844 if (!publicKeys.equals((that.publicKeys))) {
5845 return false;
5846 }
5847 } else if (that.publicKeys != null) {
5848 return false;
5849 }
5850
5851 // can't use Signature.areExactMatch() because order matters with the past signing certs
5852 if (!Arrays.equals(pastSigningCertificates, that.pastSigningCertificates)) {
5853 return false;
5854 }
5855 if (!Arrays.equals(pastSigningCertificatesFlags, that.pastSigningCertificatesFlags)) {
5856 return false;
5857 }
5858
5859 return true;
Patrick Baumann47117fc2017-12-19 10:17:21 -08005860 }
5861
5862 @Override
5863 public int hashCode() {
5864 int result = +Arrays.hashCode(signatures);
5865 result = 31 * result + signatureSchemeVersion;
5866 result = 31 * result + (publicKeys != null ? publicKeys.hashCode() : 0);
Daniel Cashman77029c52018-01-18 16:19:29 -08005867 result = 31 * result + Arrays.hashCode(pastSigningCertificates);
5868 result = 31 * result + Arrays.hashCode(pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005869 return result;
5870 }
Daniel Cashman77029c52018-01-18 16:19:29 -08005871
5872 /**
5873 * Builder of {@code SigningDetails} instances.
5874 */
5875 public static class Builder {
5876 private Signature[] mSignatures;
5877 private int mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
5878 private Signature[] mPastSigningCertificates;
5879 private int[] mPastSigningCertificatesFlags;
5880
5881 public Builder() {
5882 }
5883
5884 /** get signing certificates used to sign the current APK */
5885 public Builder setSignatures(Signature[] signatures) {
5886 mSignatures = signatures;
5887 return this;
5888 }
5889
5890 /** set the signature scheme version used to sign the APK */
5891 public Builder setSignatureSchemeVersion(int signatureSchemeVersion) {
5892 mSignatureSchemeVersion = signatureSchemeVersion;
5893 return this;
5894 }
5895
5896 /** set the signing certificates by which the APK proved it can be authenticated */
5897 public Builder setPastSigningCertificates(Signature[] pastSigningCertificates) {
5898 mPastSigningCertificates = pastSigningCertificates;
5899 return this;
5900 }
5901
5902 /** set the flags for the {@code pastSigningCertificates} */
5903 public Builder setPastSigningCertificatesFlags(int[] pastSigningCertificatesFlags) {
5904 mPastSigningCertificatesFlags = pastSigningCertificatesFlags;
5905 return this;
5906 }
5907
5908 private void checkInvariants() {
5909 // must have signatures and scheme version set
5910 if (mSignatures == null) {
5911 throw new IllegalStateException("SigningDetails requires the current signing"
5912 + " certificates.");
5913 }
5914
5915 // pastSigningCerts and flags must match up
5916 boolean pastMismatch = false;
5917 if (mPastSigningCertificates != null && mPastSigningCertificatesFlags != null) {
5918 if (mPastSigningCertificates.length != mPastSigningCertificatesFlags.length) {
5919 pastMismatch = true;
5920 }
5921 } else if (!(mPastSigningCertificates == null
5922 && mPastSigningCertificatesFlags == null)) {
5923 pastMismatch = true;
5924 }
5925 if (pastMismatch) {
5926 throw new IllegalStateException("SigningDetails must have a one to one mapping "
5927 + "between pastSigningCertificates and pastSigningCertificatesFlags");
5928 }
5929 }
5930 /** build a {@code SigningDetails} object */
5931 public SigningDetails build()
5932 throws CertificateException {
5933 checkInvariants();
5934 return new SigningDetails(mSignatures, mSignatureSchemeVersion,
5935 mPastSigningCertificates, mPastSigningCertificatesFlags);
5936 }
5937 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08005938 }
5939
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005940 /**
5941 * Representation of a full package parsed from APK files on disk. A package
5942 * consists of a single base APK, and zero or more split APKs.
5943 */
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00005944 public final static class Package implements Parcelable {
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07005945
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005946 public String packageName;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08005947
Svet Ganov67882122016-12-11 16:36:34 -08005948 // The package name declared in the manifest as the package can be
5949 // renamed, for example static shared libs use synthetic package names.
5950 public String manifestPackageName;
5951
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005952 /** Names of any split APKs, ordered by parsed splitName */
5953 public String[] splitNames;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005954
5955 // TODO: work towards making these paths invariant
Jeff Sharkey275e0852014-06-17 18:18:49 -07005956
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07005957 public String volumeUuid;
5958
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005959 /**
5960 * Path where this package was found on disk. For monolithic packages
5961 * this is path to single base APK file; for cluster packages this is
5962 * path to the cluster directory.
5963 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005964 public String codePath;
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005965
5966 /** Path of base APK */
5967 public String baseCodePath;
5968 /** Paths of any split APKs, ordered by parsed splitName */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005969 public String[] splitCodePaths;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005970
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08005971 /** Revision code of base APK */
5972 public int baseRevisionCode;
5973 /** Revision codes of any split APKs, ordered by parsed splitName */
5974 public int[] splitRevisionCodes;
5975
Jeff Sharkeyda96e132014-07-15 14:54:09 -07005976 /** Flags of any split APKs; ordered by parsed splitName */
5977 public int[] splitFlags;
5978
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005979 /**
5980 * Private flags of any split APKs; ordered by parsed splitName.
5981 *
5982 * {@hide}
5983 */
5984 public int[] splitPrivateFlags;
5985
Jeff Sharkeyda96e132014-07-15 14:54:09 -07005986 public boolean baseHardwareAccelerated;
5987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005988 // For now we only support one application per package.
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00005989 public ApplicationInfo applicationInfo = new ApplicationInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005990
5991 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
5992 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
5993 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
5994 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
5995 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
5996 public final ArrayList<Service> services = new ArrayList<Service>(0);
5997 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
5998
5999 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
6000
Dianne Hackborn854060af2009-07-09 18:14:31 -07006001 public ArrayList<String> protectedBroadcasts;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006002
Svet Ganov354cd3c2015-12-17 11:35:04 -08006003 public Package parentPackage;
6004 public ArrayList<Package> childPackages;
6005
Svet Ganov67882122016-12-11 16:36:34 -08006006 public String staticSharedLibName = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006007 public long staticSharedLibVersion = 0;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006008 public ArrayList<String> libraryNames = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07006009 public ArrayList<String> usesLibraries = null;
Svet Ganov67882122016-12-11 16:36:34 -08006010 public ArrayList<String> usesStaticLibraries = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006011 public long[] usesStaticLibrariesVersions = null;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006012 public String[][] usesStaticLibrariesCertDigests = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07006013 public ArrayList<String> usesOptionalLibraries = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006014 public String[] usesLibraryFiles = null;
6015
Dianne Hackbornb09491f2013-07-22 15:30:11 -07006016 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
6017
Dianne Hackbornc1552392010-03-03 16:19:01 -08006018 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006019 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006020 public ArrayList<String> mAdoptPermissions = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006022 // We store the application meta-data independently to avoid multiple unwanted references
6023 public Bundle mAppMetaData = null;
6024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006025 // The version code declared for this package.
6026 public int mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006027
Dianne Hackborn3accca02013-09-20 09:32:11 -07006028 // The major version code declared for this package.
6029 public int mVersionCodeMajor;
6030
6031 // Return long containing mVersionCode and mVersionCodeMajor.
6032 public long getLongVersionCode() {
6033 return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
6034 }
6035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006036 // The version name declared for this package.
6037 public String mVersionName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006039 // The shared user id that this package wants to use.
6040 public String mSharedUserId;
6041
6042 // The shared user label that this package wants to use.
6043 public int mSharedUserLabel;
6044
6045 // Signatures that were read from the package.
Patrick Baumann47117fc2017-12-19 10:17:21 -08006046 @NonNull public SigningDetails mSigningDetails = SigningDetails.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006047
6048 // For use by package manager service for quick lookup of
6049 // preferred up order.
6050 public int mPreferredOrder = 0;
6051
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006052 // For use by package manager to keep track of when a package was last used.
Brian Carlstromca82e612016-04-19 23:16:08 -07006053 public long[] mLastPackageUsageTimeInMills =
6054 new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006055
Amith Yamasani13593602012-03-22 16:16:17 -07006056 // // User set enabled state.
6057 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
6058 //
6059 // // Whether the package has been stopped.
6060 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08006061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006062 // Additional data supplied by callers.
6063 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07006064
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006065 // Applications hardware preferences
6066 public ArrayList<ConfigurationInfo> configPreferences = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006067
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006068 // Applications requested features
Dianne Hackborn49237342009-08-27 20:08:01 -07006069 public ArrayList<FeatureInfo> reqFeatures = null;
6070
Adam Lesinskid3edfde2014-08-08 17:32:44 -07006071 // Applications requested feature groups
6072 public ArrayList<FeatureGroupInfo> featureGroups = null;
6073
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08006074 public int installLocation;
6075
Jeff Hao272bf3a2014-10-08 13:34:43 -07006076 public boolean coreApp;
6077
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08006078 /* An app that's required for all users and cannot be uninstalled for a user */
6079 public boolean mRequiredForAllUsers;
6080
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07006081 /* The restricted account authenticator type that is used by this application */
6082 public String mRestrictedAccountType;
6083
Amith Yamasaniccbe3892013-04-12 17:52:42 -07006084 /* The required account type without which this application will not function */
6085 public String mRequiredAccountType;
6086
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006087 public String mOverlayTarget;
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006088 public int mOverlayPriority;
Adam Lesinskie7334972018-01-17 16:13:52 -08006089 public boolean mOverlayIsStatic;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006090
Alan Viveretteb6a25732017-11-21 14:49:24 -05006091 public int mCompileSdkVersion;
6092 public String mCompileSdkVersionCodename;
6093
Geremy Condraf1bcca82013-01-07 22:35:24 -08006094 /**
dcashman989eb3712014-06-17 12:56:12 -07006095 * Data used to feed the KeySetManagerService
Geremy Condraf1bcca82013-01-07 22:35:24 -08006096 */
dcashman989eb3712014-06-17 12:56:12 -07006097 public ArraySet<String> mUpgradeKeySets;
6098 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -08006099
Narayan Kamath4903f642014-08-11 13:33:45 +01006100 /**
6101 * The install time abi override for this package, if any.
6102 *
6103 * TODO: This seems like a horrible place to put the abiOverride because
6104 * this isn't something the packageParser parsers. However, this fits in with
6105 * the rest of the PackageManager where package scanning randomly pushes
6106 * and prods fields out of {@code this.applicationInfo}.
6107 */
6108 public String cpuAbiOverride;
Selim Gurun2d291d82016-02-05 17:50:53 -08006109 /**
6110 * The install time abi override to choose 32bit abi's when multiple abi's
6111 * are present. This is only meaningfull for multiarch applications.
6112 * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
6113 */
6114 public boolean use32bitAbi;
Narayan Kamath4903f642014-08-11 13:33:45 +01006115
Todd Kennedyfdd241a2016-04-28 12:26:53 -07006116 public byte[] restrictUpdateHash;
6117
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006118 /** Set if the app or any of its components are visible to instant applications. */
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006119 public boolean visibleToInstantApps;
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006120 /** Whether or not the package is a stub and must be replaced by the full version. */
6121 public boolean isStub;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006122
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006123 public Package(String packageName) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006124 this.packageName = packageName;
Svet Ganov67882122016-12-11 16:36:34 -08006125 this.manifestPackageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006126 applicationInfo.packageName = packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006127 applicationInfo.uid = -1;
6128 }
6129
Svet Ganov354cd3c2015-12-17 11:35:04 -08006130 public void setApplicationVolumeUuid(String volumeUuid) {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006131 final UUID storageUuid = StorageManager.convert(volumeUuid);
Svet Ganov354cd3c2015-12-17 11:35:04 -08006132 this.applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006133 this.applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006134 if (childPackages != null) {
6135 final int packageCount = childPackages.size();
6136 for (int i = 0; i < packageCount; i++) {
6137 childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006138 childPackages.get(i).applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006139 }
6140 }
6141 }
6142
6143 public void setApplicationInfoCodePath(String codePath) {
6144 this.applicationInfo.setCodePath(codePath);
6145 if (childPackages != null) {
6146 final int packageCount = childPackages.size();
6147 for (int i = 0; i < packageCount; i++) {
6148 childPackages.get(i).applicationInfo.setCodePath(codePath);
6149 }
6150 }
6151 }
6152
Todd Kennedy30a23a52018-01-04 13:27:49 -08006153 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6154 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006155 public void setApplicationInfoResourcePath(String resourcePath) {
6156 this.applicationInfo.setResourcePath(resourcePath);
6157 if (childPackages != null) {
6158 final int packageCount = childPackages.size();
6159 for (int i = 0; i < packageCount; i++) {
6160 childPackages.get(i).applicationInfo.setResourcePath(resourcePath);
6161 }
6162 }
6163 }
6164
Todd Kennedy30a23a52018-01-04 13:27:49 -08006165 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6166 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006167 public void setApplicationInfoBaseResourcePath(String resourcePath) {
6168 this.applicationInfo.setBaseResourcePath(resourcePath);
6169 if (childPackages != null) {
6170 final int packageCount = childPackages.size();
6171 for (int i = 0; i < packageCount; i++) {
6172 childPackages.get(i).applicationInfo.setBaseResourcePath(resourcePath);
6173 }
6174 }
6175 }
6176
6177 public void setApplicationInfoBaseCodePath(String baseCodePath) {
6178 this.applicationInfo.setBaseCodePath(baseCodePath);
6179 if (childPackages != null) {
6180 final int packageCount = childPackages.size();
6181 for (int i = 0; i < packageCount; i++) {
6182 childPackages.get(i).applicationInfo.setBaseCodePath(baseCodePath);
6183 }
6184 }
6185 }
6186
Todd Kennedy13715d52016-08-01 13:38:57 -07006187 public List<String> getChildPackageNames() {
6188 if (childPackages == null) {
6189 return null;
6190 }
6191 final int childCount = childPackages.size();
6192 final List<String> childPackageNames = new ArrayList<>(childCount);
6193 for (int i = 0; i < childCount; i++) {
6194 String childPackageName = childPackages.get(i).packageName;
6195 childPackageNames.add(childPackageName);
6196 }
6197 return childPackageNames;
6198 }
6199
Svet Ganov354cd3c2015-12-17 11:35:04 -08006200 public boolean hasChildPackage(String packageName) {
6201 final int childCount = (childPackages != null) ? childPackages.size() : 0;
6202 for (int i = 0; i < childCount; i++) {
6203 if (childPackages.get(i).packageName.equals(packageName)) {
6204 return true;
6205 }
6206 }
6207 return false;
6208 }
6209
6210 public void setApplicationInfoSplitCodePaths(String[] splitCodePaths) {
6211 this.applicationInfo.setSplitCodePaths(splitCodePaths);
6212 // Children have no splits
6213 }
6214
Todd Kennedy30a23a52018-01-04 13:27:49 -08006215 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6216 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006217 public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) {
6218 this.applicationInfo.setSplitResourcePaths(resroucePaths);
6219 // Children have no splits
6220 }
6221
6222 public void setSplitCodePaths(String[] codePaths) {
6223 this.splitCodePaths = codePaths;
6224 }
6225
6226 public void setCodePath(String codePath) {
6227 this.codePath = codePath;
6228 if (childPackages != null) {
6229 final int packageCount = childPackages.size();
6230 for (int i = 0; i < packageCount; i++) {
6231 childPackages.get(i).codePath = codePath;
6232 }
6233 }
6234 }
6235
6236 public void setBaseCodePath(String baseCodePath) {
6237 this.baseCodePath = baseCodePath;
6238 if (childPackages != null) {
6239 final int packageCount = childPackages.size();
6240 for (int i = 0; i < packageCount; i++) {
6241 childPackages.get(i).baseCodePath = baseCodePath;
6242 }
6243 }
6244 }
6245
Patrick Baumann47117fc2017-12-19 10:17:21 -08006246 /** Sets signing details on the package and any of its children. */
6247 public void setSigningDetails(@NonNull SigningDetails signingDetails) {
6248 mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006249 if (childPackages != null) {
6250 final int packageCount = childPackages.size();
6251 for (int i = 0; i < packageCount; i++) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08006252 childPackages.get(i).mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006253 }
6254 }
6255 }
6256
6257 public void setVolumeUuid(String volumeUuid) {
6258 this.volumeUuid = volumeUuid;
6259 if (childPackages != null) {
6260 final int packageCount = childPackages.size();
6261 for (int i = 0; i < packageCount; i++) {
6262 childPackages.get(i).volumeUuid = volumeUuid;
6263 }
6264 }
6265 }
6266
6267 public void setApplicationInfoFlags(int mask, int flags) {
6268 applicationInfo.flags = (applicationInfo.flags & ~mask) | (mask & flags);
6269 if (childPackages != null) {
6270 final int packageCount = childPackages.size();
6271 for (int i = 0; i < packageCount; i++) {
6272 childPackages.get(i).applicationInfo.flags =
6273 (applicationInfo.flags & ~mask) | (mask & flags);
6274 }
6275 }
6276 }
6277
Selim Gurun75827b22016-02-09 10:55:33 -08006278 public void setUse32bitAbi(boolean use32bitAbi) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006279 this.use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006280 if (childPackages != null) {
6281 final int packageCount = childPackages.size();
6282 for (int i = 0; i < packageCount; i++) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006283 childPackages.get(i).use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006284 }
6285 }
6286 }
6287
Svetoslav Ganov40610e32017-06-20 19:35:51 -07006288 public boolean isLibrary() {
6289 return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames);
6290 }
6291
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006292 public List<String> getAllCodePaths() {
Jeff Sharkey275e0852014-06-17 18:18:49 -07006293 ArrayList<String> paths = new ArrayList<>();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006294 paths.add(baseCodePath);
Jeff Sharkey275e0852014-06-17 18:18:49 -07006295 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6296 Collections.addAll(paths, splitCodePaths);
6297 }
6298 return paths;
6299 }
6300
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006301 /**
6302 * Filtered set of {@link #getAllCodePaths()} that excludes
6303 * resource-only APKs.
6304 */
6305 public List<String> getAllCodePathsExcludingResourceOnly() {
6306 ArrayList<String> paths = new ArrayList<>();
6307 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6308 paths.add(baseCodePath);
6309 }
6310 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6311 for (int i = 0; i < splitCodePaths.length; i++) {
6312 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6313 paths.add(splitCodePaths[i]);
6314 }
6315 }
6316 }
6317 return paths;
6318 }
6319
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006320 public void setPackageName(String newName) {
6321 packageName = newName;
6322 applicationInfo.packageName = newName;
6323 for (int i=permissions.size()-1; i>=0; i--) {
6324 permissions.get(i).setPackageName(newName);
6325 }
6326 for (int i=permissionGroups.size()-1; i>=0; i--) {
6327 permissionGroups.get(i).setPackageName(newName);
6328 }
6329 for (int i=activities.size()-1; i>=0; i--) {
6330 activities.get(i).setPackageName(newName);
6331 }
6332 for (int i=receivers.size()-1; i>=0; i--) {
6333 receivers.get(i).setPackageName(newName);
6334 }
6335 for (int i=providers.size()-1; i>=0; i--) {
6336 providers.get(i).setPackageName(newName);
6337 }
6338 for (int i=services.size()-1; i>=0; i--) {
6339 services.get(i).setPackageName(newName);
6340 }
6341 for (int i=instrumentation.size()-1; i>=0; i--) {
6342 instrumentation.get(i).setPackageName(newName);
6343 }
6344 }
Dianne Hackborn65696252012-03-05 18:49:21 -08006345
6346 public boolean hasComponentClassName(String name) {
6347 for (int i=activities.size()-1; i>=0; i--) {
6348 if (name.equals(activities.get(i).className)) {
6349 return true;
6350 }
6351 }
6352 for (int i=receivers.size()-1; i>=0; i--) {
6353 if (name.equals(receivers.get(i).className)) {
6354 return true;
6355 }
6356 }
6357 for (int i=providers.size()-1; i>=0; i--) {
6358 if (name.equals(providers.get(i).className)) {
6359 return true;
6360 }
6361 }
6362 for (int i=services.size()-1; i>=0; i--) {
6363 if (name.equals(services.get(i).className)) {
6364 return true;
6365 }
6366 }
6367 for (int i=instrumentation.size()-1; i>=0; i--) {
6368 if (name.equals(instrumentation.get(i).className)) {
6369 return true;
6370 }
6371 }
6372 return false;
6373 }
6374
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006375 /** @hide */
6376 public boolean isExternal() {
6377 return applicationInfo.isExternal();
6378 }
6379
6380 /** @hide */
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08006381 public boolean isForwardLocked() {
6382 return applicationInfo.isForwardLocked();
6383 }
6384
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006385 /** @hide */
6386 public boolean isOem() {
6387 return applicationInfo.isOem();
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006388 }
6389
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006390 /** @hide */
Jiyong Park002fdbd2017-02-13 20:50:31 +09006391 public boolean isVendor() {
6392 return applicationInfo.isVendor();
6393 }
6394
6395 /** @hide */
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006396 public boolean isPrivileged() {
Svet Ganovadc1cf42015-06-15 16:36:24 -07006397 return applicationInfo.isPrivilegedApp();
6398 }
6399
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006400 /** @hide */
6401 public boolean isSystem() {
6402 return applicationInfo.isSystemApp();
6403 }
6404
6405 /** @hide */
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006406 public boolean isUpdatedSystemApp() {
6407 return applicationInfo.isUpdatedSystemApp();
6408 }
6409
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006410 /** @hide */
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006411 public boolean canHaveOatDir() {
6412 // The following app types CANNOT have oat directory
6413 // - non-updated system apps
6414 // - forward-locked apps or apps installed in ASEC containers
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006415 return (!isSystem() || isUpdatedSystemApp())
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006416 && !isForwardLocked() && !applicationInfo.isExternalAsec();
6417 }
6418
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006419 public boolean isMatch(int flags) {
6420 if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006421 return isSystem();
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006422 }
6423 return true;
6424 }
6425
Brian Carlstromca82e612016-04-19 23:16:08 -07006426 public long getLatestPackageUseTimeInMills() {
6427 long latestUse = 0L;
6428 for (long use : mLastPackageUsageTimeInMills) {
6429 latestUse = Math.max(latestUse, use);
6430 }
6431 return latestUse;
6432 }
6433
David Brazdil90e26992016-04-18 14:08:52 +01006434 public long getLatestForegroundPackageUseTimeInMills() {
6435 int[] foregroundReasons = {
6436 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
6437 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
6438 };
6439
6440 long latestUse = 0L;
6441 for (int reason : foregroundReasons) {
6442 latestUse = Math.max(latestUse, mLastPackageUsageTimeInMills[reason]);
6443 }
6444 return latestUse;
6445 }
6446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006447 public String toString() {
6448 return "Package{"
6449 + Integer.toHexString(System.identityHashCode(this))
6450 + " " + packageName + "}";
6451 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006452
Todd Kennedyf996b762018-01-12 15:03:29 -08006453 public String dumpState_temp() {
6454 String flags = "";
6455 flags += ((applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 ? "U" : "");
6456 flags += ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 ? "S" : "");
6457 if ("".equals(flags)) {
6458 flags = "-";
6459 }
6460 String privFlags = "";
6461 privFlags += ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0 ? "P" : "");
6462 privFlags += ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0 ? "O" : "");
6463 privFlags += ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0 ? "V" : "");
6464 if ("".equals(privFlags)) {
6465 privFlags = "-";
6466 }
6467 return "Package{"
6468 + Integer.toHexString(System.identityHashCode(this))
6469 + " " + packageName
6470 + ", ver:" + getLongVersionCode()
6471 + ", path: " + codePath
6472 + ", flags: " + flags
6473 + ", privFlags: " + privFlags
6474 + ", extra: " + (mExtras == null ? "<<NULL>>" : Integer.toHexString(System.identityHashCode(mExtras)) + "}")
6475 + "}";
6476 }
6477
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006478 @Override
6479 public int describeContents() {
6480 return 0;
6481 }
6482
6483 public Package(Parcel dest) {
6484 // We use the boot classloader for all classes that we load.
6485 final ClassLoader boot = Object.class.getClassLoader();
6486
Narayan Kamath07ac1442017-02-10 15:08:07 +00006487 packageName = dest.readString().intern();
Svet Ganov67882122016-12-11 16:36:34 -08006488 manifestPackageName = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006489 splitNames = dest.readStringArray();
6490 volumeUuid = dest.readString();
6491 codePath = dest.readString();
6492 baseCodePath = dest.readString();
6493 splitCodePaths = dest.readStringArray();
6494 baseRevisionCode = dest.readInt();
6495 splitRevisionCodes = dest.createIntArray();
6496 splitFlags = dest.createIntArray();
6497 splitPrivateFlags = dest.createIntArray();
6498 baseHardwareAccelerated = (dest.readInt() == 1);
6499 applicationInfo = dest.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006500 if (applicationInfo.permission != null) {
6501 applicationInfo.permission = applicationInfo.permission.intern();
6502 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006503
6504 // We don't serialize the "owner" package and the application info object for each of
6505 // these components, in order to save space and to avoid circular dependencies while
6506 // serialization. We need to fix them all up here.
6507 dest.readParcelableList(permissions, boot);
6508 fixupOwner(permissions);
6509 dest.readParcelableList(permissionGroups, boot);
6510 fixupOwner(permissionGroups);
6511 dest.readParcelableList(activities, boot);
6512 fixupOwner(activities);
6513 dest.readParcelableList(receivers, boot);
6514 fixupOwner(receivers);
6515 dest.readParcelableList(providers, boot);
6516 fixupOwner(providers);
6517 dest.readParcelableList(services, boot);
6518 fixupOwner(services);
6519 dest.readParcelableList(instrumentation, boot);
6520 fixupOwner(instrumentation);
6521
6522 dest.readStringList(requestedPermissions);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006523 internStringArrayList(requestedPermissions);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006524 protectedBroadcasts = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006525 internStringArrayList(protectedBroadcasts);
6526
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006527 parentPackage = dest.readParcelable(boot);
6528
6529 childPackages = new ArrayList<>();
6530 dest.readParcelableList(childPackages, boot);
6531 if (childPackages.size() == 0) {
6532 childPackages = null;
6533 }
6534
Svet Ganov67882122016-12-11 16:36:34 -08006535 staticSharedLibName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006536 if (staticSharedLibName != null) {
6537 staticSharedLibName = staticSharedLibName.intern();
6538 }
Dianne Hackborn3accca02013-09-20 09:32:11 -07006539 staticSharedLibVersion = dest.readLong();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006540 libraryNames = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006541 internStringArrayList(libraryNames);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006542 usesLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006543 internStringArrayList(usesLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006544 usesOptionalLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006545 internStringArrayList(usesOptionalLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006546 usesLibraryFiles = dest.readStringArray();
6547
Svet Ganov67882122016-12-11 16:36:34 -08006548 final int libCount = dest.readInt();
6549 if (libCount > 0) {
6550 usesStaticLibraries = new ArrayList<>(libCount);
6551 dest.readStringList(usesStaticLibraries);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006552 internStringArrayList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07006553 usesStaticLibrariesVersions = new long[libCount];
6554 dest.readLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006555 usesStaticLibrariesCertDigests = new String[libCount][];
6556 for (int i = 0; i < libCount; i++) {
6557 usesStaticLibrariesCertDigests[i] = dest.createStringArray();
6558 }
Svet Ganov67882122016-12-11 16:36:34 -08006559 }
6560
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006561 preferredActivityFilters = new ArrayList<>();
6562 dest.readParcelableList(preferredActivityFilters, boot);
6563 if (preferredActivityFilters.size() == 0) {
6564 preferredActivityFilters = null;
6565 }
6566
6567 mOriginalPackages = dest.createStringArrayList();
6568 mRealPackage = dest.readString();
6569 mAdoptPermissions = dest.createStringArrayList();
6570 mAppMetaData = dest.readBundle();
6571 mVersionCode = dest.readInt();
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08006572 mVersionCodeMajor = dest.readInt();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006573 mVersionName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006574 if (mVersionName != null) {
6575 mVersionName = mVersionName.intern();
6576 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006577 mSharedUserId = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006578 if (mSharedUserId != null) {
6579 mSharedUserId = mSharedUserId.intern();
6580 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006581 mSharedUserLabel = dest.readInt();
6582
Patrick Baumann47117fc2017-12-19 10:17:21 -08006583 mSigningDetails = dest.readParcelable(boot);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006584
6585 mPreferredOrder = dest.readInt();
6586
6587 // long[] packageUsageTimeMillis is not persisted because it isn't information that
6588 // is parsed from the APK.
6589
6590 // Object mExtras is not persisted because it is not information that is read from
6591 // the APK, rather, it is supplied by callers.
6592
6593
6594 configPreferences = new ArrayList<>();
6595 dest.readParcelableList(configPreferences, boot);
6596 if (configPreferences.size() == 0) {
6597 configPreferences = null;
6598 }
6599
6600 reqFeatures = new ArrayList<>();
6601 dest.readParcelableList(reqFeatures, boot);
6602 if (reqFeatures.size() == 0) {
6603 reqFeatures = null;
6604 }
6605
6606 featureGroups = new ArrayList<>();
6607 dest.readParcelableList(featureGroups, boot);
6608 if (featureGroups.size() == 0) {
6609 featureGroups = null;
6610 }
6611
6612 installLocation = dest.readInt();
6613 coreApp = (dest.readInt() == 1);
6614 mRequiredForAllUsers = (dest.readInt() == 1);
6615 mRestrictedAccountType = dest.readString();
6616 mRequiredAccountType = dest.readString();
6617 mOverlayTarget = dest.readString();
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006618 mOverlayPriority = dest.readInt();
Adam Lesinskie7334972018-01-17 16:13:52 -08006619 mOverlayIsStatic = (dest.readInt() == 1);
Alan Viveretteb6a25732017-11-21 14:49:24 -05006620 mCompileSdkVersion = dest.readInt();
6621 mCompileSdkVersionCodename = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006622 mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
6623
6624 mKeySetMapping = readKeySetMapping(dest);
6625
6626 cpuAbiOverride = dest.readString();
6627 use32bitAbi = (dest.readInt() == 1);
6628 restrictUpdateHash = dest.createByteArray();
Chad Brubaker49f24c62017-04-05 13:08:21 -07006629 visibleToInstantApps = dest.readInt() == 1;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006630 }
6631
Narayan Kamath07ac1442017-02-10 15:08:07 +00006632 private static void internStringArrayList(List<String> list) {
6633 if (list != null) {
6634 final int N = list.size();
6635 for (int i = 0; i < N; ++i) {
6636 list.set(i, list.get(i).intern());
6637 }
6638 }
6639 }
6640
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006641 /**
6642 * Sets the package owner and the the {@code applicationInfo} for every component
6643 * owner by this package.
6644 */
6645 private void fixupOwner(List<? extends Component<?>> list) {
6646 if (list != null) {
6647 for (Component<?> c : list) {
6648 c.owner = this;
6649 if (c instanceof Activity) {
6650 ((Activity) c).info.applicationInfo = this.applicationInfo;
6651 } else if (c instanceof Service) {
6652 ((Service) c).info.applicationInfo = this.applicationInfo;
6653 } else if (c instanceof Provider) {
6654 ((Provider) c).info.applicationInfo = this.applicationInfo;
6655 }
6656 }
6657 }
6658 }
6659
6660 @Override
6661 public void writeToParcel(Parcel dest, int flags) {
6662 dest.writeString(packageName);
Svet Ganov67882122016-12-11 16:36:34 -08006663 dest.writeString(manifestPackageName);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006664 dest.writeStringArray(splitNames);
6665 dest.writeString(volumeUuid);
6666 dest.writeString(codePath);
6667 dest.writeString(baseCodePath);
6668 dest.writeStringArray(splitCodePaths);
6669 dest.writeInt(baseRevisionCode);
6670 dest.writeIntArray(splitRevisionCodes);
6671 dest.writeIntArray(splitFlags);
6672 dest.writeIntArray(splitPrivateFlags);
6673 dest.writeInt(baseHardwareAccelerated ? 1 : 0);
6674 dest.writeParcelable(applicationInfo, flags);
6675
6676 dest.writeParcelableList(permissions, flags);
6677 dest.writeParcelableList(permissionGroups, flags);
6678 dest.writeParcelableList(activities, flags);
6679 dest.writeParcelableList(receivers, flags);
6680 dest.writeParcelableList(providers, flags);
6681 dest.writeParcelableList(services, flags);
6682 dest.writeParcelableList(instrumentation, flags);
6683
6684 dest.writeStringList(requestedPermissions);
6685 dest.writeStringList(protectedBroadcasts);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07006686
6687 // TODO: This doesn't work: b/64295061
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006688 dest.writeParcelable(parentPackage, flags);
6689 dest.writeParcelableList(childPackages, flags);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07006690
Svet Ganov67882122016-12-11 16:36:34 -08006691 dest.writeString(staticSharedLibName);
Dianne Hackborn3accca02013-09-20 09:32:11 -07006692 dest.writeLong(staticSharedLibVersion);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006693 dest.writeStringList(libraryNames);
6694 dest.writeStringList(usesLibraries);
6695 dest.writeStringList(usesOptionalLibraries);
6696 dest.writeStringArray(usesLibraryFiles);
6697
Svet Ganov67882122016-12-11 16:36:34 -08006698 if (ArrayUtils.isEmpty(usesStaticLibraries)) {
6699 dest.writeInt(-1);
6700 } else {
6701 dest.writeInt(usesStaticLibraries.size());
6702 dest.writeStringList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07006703 dest.writeLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006704 for (String[] usesStaticLibrariesCertDigest : usesStaticLibrariesCertDigests) {
6705 dest.writeStringArray(usesStaticLibrariesCertDigest);
6706 }
Svet Ganov67882122016-12-11 16:36:34 -08006707 }
6708
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006709 dest.writeParcelableList(preferredActivityFilters, flags);
6710
6711 dest.writeStringList(mOriginalPackages);
6712 dest.writeString(mRealPackage);
6713 dest.writeStringList(mAdoptPermissions);
6714 dest.writeBundle(mAppMetaData);
6715 dest.writeInt(mVersionCode);
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08006716 dest.writeInt(mVersionCodeMajor);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006717 dest.writeString(mVersionName);
6718 dest.writeString(mSharedUserId);
6719 dest.writeInt(mSharedUserLabel);
6720
Patrick Baumann47117fc2017-12-19 10:17:21 -08006721 dest.writeParcelable(mSigningDetails, flags);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006722
6723 dest.writeInt(mPreferredOrder);
6724
6725 // long[] packageUsageTimeMillis is not persisted because it isn't information that
6726 // is parsed from the APK.
6727
6728 // Object mExtras is not persisted because it is not information that is read from
6729 // the APK, rather, it is supplied by callers.
6730
6731 dest.writeParcelableList(configPreferences, flags);
6732 dest.writeParcelableList(reqFeatures, flags);
6733 dest.writeParcelableList(featureGroups, flags);
6734
6735 dest.writeInt(installLocation);
6736 dest.writeInt(coreApp ? 1 : 0);
6737 dest.writeInt(mRequiredForAllUsers ? 1 : 0);
6738 dest.writeString(mRestrictedAccountType);
6739 dest.writeString(mRequiredAccountType);
6740 dest.writeString(mOverlayTarget);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006741 dest.writeInt(mOverlayPriority);
Adam Lesinskie7334972018-01-17 16:13:52 -08006742 dest.writeInt(mOverlayIsStatic ? 1 : 0);
Alan Viveretteb6a25732017-11-21 14:49:24 -05006743 dest.writeInt(mCompileSdkVersion);
6744 dest.writeString(mCompileSdkVersionCodename);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006745 dest.writeArraySet(mUpgradeKeySets);
6746 writeKeySetMapping(dest, mKeySetMapping);
6747 dest.writeString(cpuAbiOverride);
6748 dest.writeInt(use32bitAbi ? 1 : 0);
6749 dest.writeByteArray(restrictUpdateHash);
Chad Brubaker49f24c62017-04-05 13:08:21 -07006750 dest.writeInt(visibleToInstantApps ? 1 : 0);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006751 }
6752
6753
6754 /**
6755 * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
6756 */
6757 private static void writeKeySetMapping(
6758 Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
6759 if (keySetMapping == null) {
6760 dest.writeInt(-1);
6761 return;
6762 }
6763
6764 final int N = keySetMapping.size();
6765 dest.writeInt(N);
6766
6767 for (int i = 0; i < N; i++) {
6768 dest.writeString(keySetMapping.keyAt(i));
6769 ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
6770 if (keys == null) {
6771 dest.writeInt(-1);
6772 continue;
6773 }
6774
6775 final int M = keys.size();
6776 dest.writeInt(M);
6777 for (int j = 0; j < M; j++) {
6778 dest.writeSerializable(keys.valueAt(j));
6779 }
6780 }
6781 }
6782
6783 /**
6784 * Reads a keyset mapping from the given parcel at the given data position. May return
6785 * {@code null} if the serialized mapping was {@code null}.
6786 */
6787 private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
6788 final int N = in.readInt();
6789 if (N == -1) {
6790 return null;
6791 }
6792
6793 ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
6794 for (int i = 0; i < N; ++i) {
6795 String key = in.readString();
6796 final int M = in.readInt();
6797 if (M == -1) {
6798 keySetMapping.put(key, null);
6799 continue;
6800 }
6801
6802 ArraySet<PublicKey> keys = new ArraySet<>(M);
6803 for (int j = 0; j < M; ++j) {
6804 PublicKey pk = (PublicKey) in.readSerializable();
6805 keys.add(pk);
6806 }
6807
6808 keySetMapping.put(key, keys);
6809 }
6810
6811 return keySetMapping;
6812 }
6813
6814 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
6815 public Package createFromParcel(Parcel in) {
6816 return new Package(in);
6817 }
6818
6819 public Package[] newArray(int size) {
6820 return new Package[size];
6821 }
6822 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006823 }
6824
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006825 public static abstract class Component<II extends IntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006826 public final ArrayList<II> intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006827 public final String className;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006829 public Bundle metaData;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006830 public Package owner;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006831
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006832 ComponentName componentName;
6833 String componentShortName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006835 public Component(Package _owner) {
6836 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006837 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006838 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006839 }
6840
6841 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
6842 owner = args.owner;
6843 intents = new ArrayList<II>(0);
Todd Kennedybb8a42d2016-06-02 14:13:56 -07006844 if (parsePackageItemInfo(args.owner, outInfo, args.outError, args.tag, args.sa,
6845 true /*nameRequired*/, args.nameRes, args.labelRes, args.iconRes,
6846 args.roundIconRes, args.logoRes, args.bannerRes)) {
6847 className = outInfo.name;
6848 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006849 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006850 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006851 }
6852
6853 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
6854 this(args, (PackageItemInfo)outInfo);
6855 if (args.outError[0] != null) {
6856 return;
6857 }
6858
6859 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07006860 CharSequence pname;
6861 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07006862 pname = args.sa.getNonConfigurationString(args.processRes,
6863 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07006864 } else {
6865 // Some older apps have been seen to use a resource reference
6866 // here that on older builds was ignored (with a warning). We
6867 // need to continue to do this for them so they don't break.
6868 pname = args.sa.getNonResourceString(args.processRes);
6869 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006870 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07006871 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006872 args.flags, args.sepProcesses, args.outError);
6873 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006874
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08006875 if (args.descriptionRes != 0) {
6876 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
6877 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006878
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006879 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006880 }
6881
6882 public Component(Component<II> clone) {
6883 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006884 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006885 className = clone.className;
6886 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006887 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006888 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006889
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006890 public ComponentName getComponentName() {
6891 if (componentName != null) {
6892 return componentName;
6893 }
6894 if (className != null) {
6895 componentName = new ComponentName(owner.applicationInfo.packageName,
6896 className);
6897 }
6898 return componentName;
6899 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07006900
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006901 protected Component(Parcel in) {
6902 className = in.readString();
6903 metaData = in.readBundle();
6904 intents = createIntentsList(in);
6905
6906 owner = null;
6907 }
6908
6909 protected void writeToParcel(Parcel dest, int flags) {
6910 dest.writeString(className);
6911 dest.writeBundle(metaData);
6912
6913 writeIntentsList(intents, dest, flags);
6914 }
6915
6916 /**
6917 * <p>
6918 * Implementation note: The serialized form for the intent list also contains the name
6919 * of the concrete class that's stored in the list, and assumes that every element of the
6920 * list is of the same type. This is very similar to the original parcelable mechanism.
6921 * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable
6922 * and is public API. It also declares Parcelable related methods as final which means
6923 * we can't extend them. The approach of using composition instead of inheritance leads to
6924 * a large set of cascading changes in the PackageManagerService, which seem undesirable.
6925 *
6926 * <p>
6927 * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up
6928 * to make sure their owner fields are consistent. See {@code fixupOwner}.
6929 */
6930 private static void writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out,
6931 int flags) {
6932 if (list == null) {
6933 out.writeInt(-1);
6934 return;
6935 }
6936
6937 final int N = list.size();
6938 out.writeInt(N);
6939
6940 // Don't bother writing the component name if the list is empty.
6941 if (N > 0) {
6942 IntentInfo info = list.get(0);
6943 out.writeString(info.getClass().getName());
6944
6945 for (int i = 0; i < N;i++) {
6946 list.get(i).writeIntentInfoToParcel(out, flags);
6947 }
6948 }
6949 }
6950
6951 private static <T extends IntentInfo> ArrayList<T> createIntentsList(Parcel in) {
6952 int N = in.readInt();
6953 if (N == -1) {
6954 return null;
6955 }
6956
6957 if (N == 0) {
6958 return new ArrayList<>(0);
6959 }
6960
6961 String componentName = in.readString();
6962 final ArrayList<T> intentsList;
6963 try {
6964 final Class<T> cls = (Class<T>) Class.forName(componentName);
6965 final Constructor<T> cons = cls.getConstructor(Parcel.class);
6966
6967 intentsList = new ArrayList<>(N);
6968 for (int i = 0; i < N; ++i) {
6969 intentsList.add(cons.newInstance(in));
6970 }
6971 } catch (ReflectiveOperationException ree) {
6972 throw new AssertionError("Unable to construct intent list for: " + componentName);
6973 }
6974
6975 return intentsList;
6976 }
6977
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07006978 public void appendComponentShortName(StringBuilder sb) {
6979 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006980 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07006981
6982 public void printComponentShortName(PrintWriter pw) {
6983 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
6984 }
6985
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006986 public void setPackageName(String packageName) {
6987 componentName = null;
6988 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006989 }
6990 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006991
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006992 public final static class Permission extends Component<IntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006993 public final PermissionInfo info;
6994 public boolean tree;
6995 public PermissionGroup group;
6996
6997 public Permission(Package _owner) {
6998 super(_owner);
6999 info = new PermissionInfo();
7000 }
7001
7002 public Permission(Package _owner, PermissionInfo _info) {
7003 super(_owner);
7004 info = _info;
7005 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007006
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007007 public void setPackageName(String packageName) {
7008 super.setPackageName(packageName);
7009 info.packageName = packageName;
7010 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007011
7012 public String toString() {
7013 return "Permission{"
7014 + Integer.toHexString(System.identityHashCode(this))
7015 + " " + info.name + "}";
7016 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007017
7018 @Override
7019 public int describeContents() {
7020 return 0;
7021 }
7022
7023 @Override
7024 public void writeToParcel(Parcel dest, int flags) {
7025 super.writeToParcel(dest, flags);
7026 dest.writeParcelable(info, flags);
7027 dest.writeInt(tree ? 1 : 0);
7028 dest.writeParcelable(group, flags);
7029 }
7030
Todd Kennedyc8423932017-10-05 08:58:36 -07007031 /** @hide */
7032 public boolean isAppOp() {
7033 return info.isAppOp();
7034 }
7035
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007036 private Permission(Parcel in) {
7037 super(in);
7038 final ClassLoader boot = Object.class.getClassLoader();
7039 info = in.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00007040 if (info.group != null) {
7041 info.group = info.group.intern();
7042 }
7043
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007044 tree = (in.readInt() == 1);
7045 group = in.readParcelable(boot);
7046 }
7047
7048 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Permission>() {
7049 public Permission createFromParcel(Parcel in) {
7050 return new Permission(in);
7051 }
7052
7053 public Permission[] newArray(int size) {
7054 return new Permission[size];
7055 }
7056 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007057 }
7058
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007059 public final static class PermissionGroup extends Component<IntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007060 public final PermissionGroupInfo info;
7061
7062 public PermissionGroup(Package _owner) {
7063 super(_owner);
7064 info = new PermissionGroupInfo();
7065 }
7066
7067 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
7068 super(_owner);
7069 info = _info;
7070 }
7071
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007072 public void setPackageName(String packageName) {
7073 super.setPackageName(packageName);
7074 info.packageName = packageName;
7075 }
7076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007077 public String toString() {
7078 return "PermissionGroup{"
7079 + Integer.toHexString(System.identityHashCode(this))
7080 + " " + info.name + "}";
7081 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007082
7083 @Override
7084 public int describeContents() {
7085 return 0;
7086 }
7087
7088 @Override
7089 public void writeToParcel(Parcel dest, int flags) {
7090 super.writeToParcel(dest, flags);
7091 dest.writeParcelable(info, flags);
7092 }
7093
7094 private PermissionGroup(Parcel in) {
7095 super(in);
7096 info = in.readParcelable(Object.class.getClassLoader());
7097 }
7098
7099 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<PermissionGroup>() {
7100 public PermissionGroup createFromParcel(Parcel in) {
7101 return new PermissionGroup(in);
7102 }
7103
7104 public PermissionGroup[] newArray(int size) {
7105 return new PermissionGroup[size];
7106 }
7107 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007108 }
7109
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007110 private static boolean copyNeeded(int flags, Package p,
7111 PackageUserState state, Bundle metaData, int userId) {
Xiaohui Chen98404fd2015-08-17 16:09:02 -07007112 if (userId != UserHandle.USER_SYSTEM) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007113 // We always need to copy for other users, since we need
7114 // to fix up the uid.
7115 return true;
7116 }
7117 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
7118 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07007119 if (p.applicationInfo.enabled != enabled) {
7120 return true;
7121 }
7122 }
Rubin Xubf67c9c2016-04-20 17:09:38 +01007123 boolean suspended = (p.applicationInfo.flags & FLAG_SUSPENDED) != 0;
7124 if (state.suspended != suspended) {
7125 return true;
7126 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007127 if (!state.installed || state.hidden) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007128 return true;
7129 }
7130 if (state.stopped) {
7131 return true;
7132 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007133 if (state.instantApp != p.applicationInfo.isInstantApp()) {
7134 return true;
7135 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007136 if ((flags & PackageManager.GET_META_DATA) != 0
7137 && (metaData != null || p.mAppMetaData != null)) {
7138 return true;
7139 }
7140 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
7141 && p.usesLibraryFiles != null) {
7142 return true;
7143 }
Svet Ganov67882122016-12-11 16:36:34 -08007144 if (p.staticSharedLibName != null) {
7145 return true;
7146 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007147 return false;
7148 }
7149
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007150 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
7151 PackageUserState state) {
7152 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07007153 }
7154
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007155 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
7156 PackageUserState state) {
7157 // CompatibilityMode is global state.
7158 if (!sCompatibilityModeEnabled) {
7159 ai.disableCompatibilityMode();
7160 }
7161 if (state.installed) {
7162 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
7163 } else {
7164 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
7165 }
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00007166 if (state.suspended) {
7167 ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
7168 } else {
7169 ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
7170 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007171 if (state.instantApp) {
7172 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT;
7173 } else {
7174 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT;
7175 }
Todd Kennedy5eb5a7d2017-08-01 07:42:47 -07007176 if (state.virtualPreload) {
7177 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7178 } else {
7179 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7180 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007181 if (state.hidden) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007182 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007183 } else {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007184 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007185 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007186 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
7187 ai.enabled = true;
7188 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
7189 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
7190 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
7191 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
7192 ai.enabled = false;
7193 }
7194 ai.enabledSetting = state.enabled;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07007195 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7196 ai.category = state.categoryHint;
7197 }
Jeff Sharkey0078e1b2017-01-11 16:05:27 -07007198 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7199 ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
7200 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007201 ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
Todd Kennedyb2749472017-06-13 08:24:32 -07007202 ai.resourceDirs = state.overlayPaths;
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007203 }
7204
Amith Yamasani13593602012-03-22 16:16:17 -07007205 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007206 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007207 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007208 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007209 return null;
7210 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007211 if (!copyNeeded(flags, p, state, null, userId)
7212 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
7213 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
7214 // In this case it is safe to directly modify the internal ApplicationInfo state:
7215 // - CompatibilityMode is global state, so will be the same for every call.
7216 // - We only come in to here if the app should reported as installed; this is the
7217 // default state, and we will do a copy otherwise.
7218 // - The enable state will always be reported the same for the application across
7219 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
7220 // be doing a copy.
7221 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007222 return p.applicationInfo;
7223 }
7224
7225 // Make shallow copy so we can store the metadata/libraries safely
7226 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Jeff Sharkey15447792015-11-05 16:18:51 -08007227 ai.initForUser(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007228 if ((flags & PackageManager.GET_META_DATA) != 0) {
7229 ai.metaData = p.mAppMetaData;
7230 }
7231 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
7232 ai.sharedLibraryFiles = p.usesLibraryFiles;
7233 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007234 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007235 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007236 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007237 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007238 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007239 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007240 return ai;
7241 }
7242
Dianne Hackbornace27912014-09-18 18:38:30 -07007243 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
7244 PackageUserState state, int userId) {
7245 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007246 if (!checkUseInstalledOrHidden(flags, state, ai)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007247 return null;
7248 }
7249 // This is only used to return the ResolverActivity; we will just always
7250 // make a copy.
7251 ai = new ApplicationInfo(ai);
Jeff Sharkey15447792015-11-05 16:18:51 -08007252 ai.initForUser(userId);
Dianne Hackbornace27912014-09-18 18:38:30 -07007253 if (state.stopped) {
7254 ai.flags |= ApplicationInfo.FLAG_STOPPED;
7255 } else {
7256 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
7257 }
7258 updateApplicationInfo(ai, flags, state);
7259 return ai;
7260 }
7261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007262 public static final PermissionInfo generatePermissionInfo(
7263 Permission p, int flags) {
7264 if (p == null) return null;
7265 if ((flags&PackageManager.GET_META_DATA) == 0) {
7266 return p.info;
7267 }
7268 PermissionInfo pi = new PermissionInfo(p.info);
7269 pi.metaData = p.metaData;
7270 return pi;
7271 }
7272
7273 public static final PermissionGroupInfo generatePermissionGroupInfo(
7274 PermissionGroup pg, int flags) {
7275 if (pg == null) return null;
7276 if ((flags&PackageManager.GET_META_DATA) == 0) {
7277 return pg.info;
7278 }
7279 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
7280 pgi.metaData = pg.metaData;
7281 return pgi;
7282 }
7283
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007284 public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007285 public final ActivityInfo info;
Bryce Lee22571db2017-07-07 15:54:18 -07007286 private boolean mHasMaxAspectRatio;
7287
7288 private boolean hasMaxAspectRatio() {
7289 return mHasMaxAspectRatio;
7290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007291
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007292 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
7293 super(args, _info);
7294 info = _info;
7295 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007296 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007297
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007298 public void setPackageName(String packageName) {
7299 super.setPackageName(packageName);
7300 info.packageName = packageName;
7301 }
7302
Bryce Lee22571db2017-07-07 15:54:18 -07007303
7304 private void setMaxAspectRatio(float maxAspectRatio) {
7305 if (info.resizeMode == RESIZE_MODE_RESIZEABLE
7306 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
7307 // Resizeable activities can be put in any aspect ratio.
7308 return;
7309 }
7310
7311 if (maxAspectRatio < 1.0f && maxAspectRatio != 0) {
7312 // Ignore any value lesser than 1.0.
7313 return;
7314 }
7315
7316 info.maxAspectRatio = maxAspectRatio;
7317 mHasMaxAspectRatio = true;
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("Activity{");
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);
Bryce Lee22571db2017-07-07 15:54:18 -07007339 dest.writeBoolean(mHasMaxAspectRatio);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007340 }
7341
7342 private Activity(Parcel in) {
7343 super(in);
7344 info = in.readParcelable(Object.class.getClassLoader());
Bryce Lee22571db2017-07-07 15:54:18 -07007345 mHasMaxAspectRatio = in.readBoolean();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007346
7347 for (ActivityIntentInfo aii : intents) {
7348 aii.activity = this;
7349 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007350
7351 if (info.permission != null) {
7352 info.permission = info.permission.intern();
7353 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007354 }
7355
7356 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Activity>() {
7357 public Activity createFromParcel(Parcel in) {
7358 return new Activity(in);
7359 }
7360
7361 public Activity[] newArray(int size) {
7362 return new Activity[size];
7363 }
7364 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007365 }
7366
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007367 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
7368 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007369 if (a == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007370 if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007371 return null;
7372 }
7373 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007374 updateApplicationInfo(a.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007375 return a.info;
7376 }
7377 // Make shallow copies so we can store the metadata safely
7378 ActivityInfo ai = new ActivityInfo(a.info);
7379 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007380 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007381 return ai;
7382 }
7383
Dianne Hackbornace27912014-09-18 18:38:30 -07007384 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
7385 PackageUserState state, int userId) {
7386 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007387 if (!checkUseInstalledOrHidden(flags, state, ai.applicationInfo)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007388 return null;
7389 }
7390 // This is only used to return the ResolverActivity; we will just always
7391 // make a copy.
7392 ai = new ActivityInfo(ai);
7393 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
7394 return ai;
7395 }
7396
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007397 public final static class Service extends Component<ServiceIntentInfo> implements Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007398 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007399
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007400 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
7401 super(args, _info);
7402 info = _info;
7403 info.applicationInfo = args.owner.applicationInfo;
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("Service{");
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 | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
7430 }
7431
7432 private Service(Parcel in) {
7433 super(in);
7434 info = in.readParcelable(Object.class.getClassLoader());
7435
7436 for (ServiceIntentInfo aii : intents) {
7437 aii.service = this;
7438 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007439
7440 if (info.permission != null) {
7441 info.permission = info.permission.intern();
7442 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007443 }
7444
7445 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Service>() {
7446 public Service createFromParcel(Parcel in) {
7447 return new Service(in);
7448 }
7449
7450 public Service[] newArray(int size) {
7451 return new Service[size];
7452 }
7453 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007454 }
7455
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007456 public static final ServiceInfo generateServiceInfo(Service s, int flags,
7457 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007458 if (s == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007459 if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007460 return null;
7461 }
7462 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007463 updateApplicationInfo(s.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007464 return s.info;
7465 }
7466 // Make shallow copies so we can store the metadata safely
7467 ServiceInfo si = new ServiceInfo(s.info);
7468 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007469 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007470 return si;
7471 }
7472
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007473 public final static class Provider extends Component<ProviderIntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007474 public final ProviderInfo info;
7475 public boolean syncable;
7476
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007477 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
7478 super(args, _info);
7479 info = _info;
7480 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007481 syncable = false;
7482 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007484 public Provider(Provider existingProvider) {
7485 super(existingProvider);
7486 this.info = existingProvider.info;
7487 this.syncable = existingProvider.syncable;
7488 }
7489
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007490 public void setPackageName(String packageName) {
7491 super.setPackageName(packageName);
7492 info.packageName = packageName;
7493 }
7494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007495 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007496 StringBuilder sb = new StringBuilder(128);
7497 sb.append("Provider{");
7498 sb.append(Integer.toHexString(System.identityHashCode(this)));
7499 sb.append(' ');
7500 appendComponentShortName(sb);
7501 sb.append('}');
7502 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007503 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007504
7505 @Override
7506 public int describeContents() {
7507 return 0;
7508 }
7509
7510 @Override
7511 public void writeToParcel(Parcel dest, int flags) {
7512 super.writeToParcel(dest, flags);
7513 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
7514 dest.writeInt((syncable) ? 1 : 0);
7515 }
7516
7517 private Provider(Parcel in) {
7518 super(in);
7519 info = in.readParcelable(Object.class.getClassLoader());
7520 syncable = (in.readInt() == 1);
7521
7522 for (ProviderIntentInfo aii : intents) {
7523 aii.provider = this;
7524 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007525
7526 if (info.readPermission != null) {
7527 info.readPermission = info.readPermission.intern();
7528 }
7529
7530 if (info.writePermission != null) {
7531 info.writePermission = info.writePermission.intern();
7532 }
7533
7534 if (info.authority != null) {
7535 info.authority = info.authority.intern();
7536 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007537 }
7538
7539 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Provider>() {
7540 public Provider createFromParcel(Parcel in) {
7541 return new Provider(in);
7542 }
7543
7544 public Provider[] newArray(int size) {
7545 return new Provider[size];
7546 }
7547 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007548 }
7549
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007550 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
7551 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007552 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007553 if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007554 return null;
7555 }
7556 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007557 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007558 || p.info.uriPermissionPatterns == null)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007559 updateApplicationInfo(p.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007560 return p.info;
7561 }
7562 // Make shallow copies so we can store the metadata safely
7563 ProviderInfo pi = new ProviderInfo(p.info);
7564 pi.metaData = p.metaData;
7565 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
7566 pi.uriPermissionPatterns = null;
7567 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007568 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007569 return pi;
7570 }
7571
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007572 public final static class Instrumentation extends Component<IntentInfo> implements
7573 Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007574 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007575
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007576 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
7577 super(args, _info);
7578 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007579 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007580
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007581 public void setPackageName(String packageName) {
7582 super.setPackageName(packageName);
7583 info.packageName = packageName;
7584 }
7585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007586 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007587 StringBuilder sb = new StringBuilder(128);
7588 sb.append("Instrumentation{");
7589 sb.append(Integer.toHexString(System.identityHashCode(this)));
7590 sb.append(' ');
7591 appendComponentShortName(sb);
7592 sb.append('}');
7593 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007594 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007595
7596 @Override
7597 public int describeContents() {
7598 return 0;
7599 }
7600
7601 @Override
7602 public void writeToParcel(Parcel dest, int flags) {
7603 super.writeToParcel(dest, flags);
7604 dest.writeParcelable(info, flags);
7605 }
7606
7607 private Instrumentation(Parcel in) {
7608 super(in);
7609 info = in.readParcelable(Object.class.getClassLoader());
Narayan Kamath07ac1442017-02-10 15:08:07 +00007610
7611 if (info.targetPackage != null) {
7612 info.targetPackage = info.targetPackage.intern();
7613 }
7614
Dianne Hackborn1be53542017-04-28 13:36:00 -07007615 if (info.targetProcesses != null) {
7616 info.targetProcesses = info.targetProcesses.intern();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007617 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007618 }
7619
7620 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Instrumentation>() {
7621 public Instrumentation createFromParcel(Parcel in) {
7622 return new Instrumentation(in);
7623 }
7624
7625 public Instrumentation[] newArray(int size) {
7626 return new Instrumentation[size];
7627 }
7628 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007629 }
7630
7631 public static final InstrumentationInfo generateInstrumentationInfo(
7632 Instrumentation i, int flags) {
7633 if (i == null) return null;
7634 if ((flags&PackageManager.GET_META_DATA) == 0) {
7635 return i.info;
7636 }
7637 InstrumentationInfo ii = new InstrumentationInfo(i.info);
7638 ii.metaData = i.metaData;
7639 return ii;
7640 }
7641
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007642 public static abstract class IntentInfo extends IntentFilter {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007643 public boolean hasDefault;
7644 public int labelRes;
7645 public CharSequence nonLocalizedLabel;
7646 public int icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07007647 public int logo;
Jose Limaf78e3122014-03-06 12:13:15 -08007648 public int banner;
Dianne Hackbornb09491f2013-07-22 15:30:11 -07007649 public int preferred;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007650
7651 protected IntentInfo() {
7652 }
7653
7654 protected IntentInfo(Parcel dest) {
7655 super(dest);
7656 hasDefault = (dest.readInt() == 1);
7657 labelRes = dest.readInt();
7658 nonLocalizedLabel = dest.readCharSequence();
7659 icon = dest.readInt();
7660 logo = dest.readInt();
7661 banner = dest.readInt();
7662 preferred = dest.readInt();
7663 }
7664
7665
7666 public void writeIntentInfoToParcel(Parcel dest, int flags) {
7667 super.writeToParcel(dest, flags);
7668 dest.writeInt(hasDefault ? 1 : 0);
7669 dest.writeInt(labelRes);
7670 dest.writeCharSequence(nonLocalizedLabel);
7671 dest.writeInt(icon);
7672 dest.writeInt(logo);
7673 dest.writeInt(banner);
7674 dest.writeInt(preferred);
7675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007676 }
7677
7678 public final static class ActivityIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007679 public Activity activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007680
7681 public ActivityIntentInfo(Activity _activity) {
7682 activity = _activity;
7683 }
7684
7685 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007686 StringBuilder sb = new StringBuilder(128);
7687 sb.append("ActivityIntentInfo{");
7688 sb.append(Integer.toHexString(System.identityHashCode(this)));
7689 sb.append(' ');
7690 activity.appendComponentShortName(sb);
7691 sb.append('}');
7692 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007693 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007694
7695 public ActivityIntentInfo(Parcel in) {
7696 super(in);
7697 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007698 }
7699
7700 public final static class ServiceIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007701 public Service service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007702
7703 public ServiceIntentInfo(Service _service) {
7704 service = _service;
7705 }
7706
7707 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007708 StringBuilder sb = new StringBuilder(128);
7709 sb.append("ServiceIntentInfo{");
7710 sb.append(Integer.toHexString(System.identityHashCode(this)));
7711 sb.append(' ');
7712 service.appendComponentShortName(sb);
7713 sb.append('}');
7714 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007715 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007716
7717 public ServiceIntentInfo(Parcel in) {
7718 super(in);
7719 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007720 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007721
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007722 public static final class ProviderIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007723 public Provider provider;
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007724
7725 public ProviderIntentInfo(Provider provider) {
7726 this.provider = provider;
7727 }
7728
7729 public String toString() {
7730 StringBuilder sb = new StringBuilder(128);
7731 sb.append("ProviderIntentInfo{");
7732 sb.append(Integer.toHexString(System.identityHashCode(this)));
7733 sb.append(' ');
7734 provider.appendComponentShortName(sb);
7735 sb.append('}');
7736 return sb.toString();
7737 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007738
7739 public ProviderIntentInfo(Parcel in) {
7740 super(in);
7741 }
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007742 }
7743
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007744 /**
7745 * @hide
7746 */
7747 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
7748 sCompatibilityModeEnabled = compatibilityModeEnabled;
7749 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07007750
7751 public static class PackageParserException extends Exception {
7752 public final int error;
7753
7754 public PackageParserException(int error, String detailMessage) {
7755 super(detailMessage);
7756 this.error = error;
7757 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07007758
7759 public PackageParserException(int error, String detailMessage, Throwable throwable) {
7760 super(detailMessage, throwable);
7761 this.error = error;
7762 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07007763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007764}