blob: 5b5ccf547b540676334ef69fa22c665cf476d753 [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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import android.content.res.AssetManager;
58import android.content.res.Configuration;
59import android.content.res.Resources;
60import android.content.res.TypedArray;
61import android.content.res.XmlResourceParser;
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -070062import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.os.Bundle;
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -070064import android.os.FileUtils;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070065import android.os.Parcel;
66import android.os.Parcelable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.os.PatternMatcher;
Fyodor Kupolov28a988f2017-07-31 18:44:11 -070068import android.os.SystemClock;
Todd Leeea2f3be2017-03-16 14:00:52 -070069import android.os.SystemProperties;
Todd Kennedy27c24fb2015-09-17 16:49:25 -070070import android.os.Trace;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070071import android.os.UserHandle;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -060072import android.os.storage.StorageManager;
Narayan Kamath988149c2016-12-01 13:32:59 +000073import android.system.ErrnoException;
74import android.system.OsConstants;
75import android.system.StructStat;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -070076import android.text.TextUtils;
Jeff Sharkey275e0852014-06-17 18:18:49 -070077import android.util.ArrayMap;
78import android.util.ArraySet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079import android.util.AttributeSet;
Kenny Root05ca4c92011-09-15 10:36:25 -070080import android.util.Base64;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import android.util.DisplayMetrics;
Kenny Root05ca4c92011-09-15 10:36:25 -070082import android.util.Log;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070083import android.util.Pair;
Kenny Rootd2d29252011-08-08 11:27:57 -070084import android.util.Slog;
Adam Lesinski1665d0f2017-03-10 14:46:57 -080085import android.util.SparseArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import android.util.TypedValue;
Dan Cashmane92f8422017-12-08 14:02:51 -080087import android.util.apk.ApkSignatureVerifier;
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -070088import android.view.Gravity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070090import com.android.internal.R;
91import com.android.internal.annotations.VisibleForTesting;
Narayan Kamathf9419f02017-06-15 11:35:38 +010092import com.android.internal.os.ClassLoaderFactory;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070093import com.android.internal.util.ArrayUtils;
94import com.android.internal.util.XmlUtils;
95
96import libcore.io.IoUtils;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -070097import libcore.util.EmptyArray;
Svet Ganov087dce22017-09-07 15:42:16 -070098
Jeff Sharkey9bc89af2017-01-11 11:25:50 -070099import org.xmlpull.v1.XmlPullParser;
100import org.xmlpull.v1.XmlPullParserException;
101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import java.io.File;
Dianne Hackbornca3872c2017-10-30 14:19:32 -0700103import java.io.FileDescriptor;
Narayan Kamath988149c2016-12-01 13:32:59 +0000104import java.io.FileOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import java.io.IOException;
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -0700106import java.io.PrintWriter;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800107import java.lang.annotation.Retention;
108import java.lang.annotation.RetentionPolicy;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000109import java.lang.reflect.Constructor;
Kenny Root05ca4c92011-09-15 10:36:25 -0700110import java.security.KeyFactory;
111import java.security.NoSuchAlgorithmException;
112import java.security.PublicKey;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800113import java.security.cert.CertificateException;
Kenny Root05ca4c92011-09-15 10:36:25 -0700114import java.security.spec.EncodedKeySpec;
115import java.security.spec.InvalidKeySpecException;
116import java.security.spec.X509EncodedKeySpec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117import java.util.ArrayList;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700118import java.util.Arrays;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700119import java.util.Collections;
120import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121import java.util.Iterator;
Kenny Root05ca4c92011-09-15 10:36:25 -0700122import java.util.List;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800123import java.util.Set;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -0600124import java.util.UUID;
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700125import java.util.concurrent.atomic.AtomicInteger;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126
127/**
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700128 * Parser for package files (APKs) on disk. This supports apps packaged either
129 * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
130 * APKs in a single directory.
131 * <p>
132 * Apps packaged as multiple APKs always consist of a single "base" APK (with a
133 * {@code null} split name) and zero or more "split" APKs (with unique split
134 * names). Any subset of those split APKs are a valid install, as long as the
135 * following constraints are met:
136 * <ul>
137 * <li>All APKs must have the exact same package name, version code, and signing
138 * certificates.
139 * <li>All APKs must have unique split names.
140 * <li>All installations must contain a single base APK.
141 * </ul>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700143 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144 */
145public class PackageParser {
Kenny Rootd2d29252011-08-08 11:27:57 -0700146 private static final boolean DEBUG_JAR = false;
147 private static final boolean DEBUG_PARSER = false;
148 private static final boolean DEBUG_BACKUP = false;
Fyodor Kupolov28a988f2017-07-31 18:44:11 -0700149 private static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE;
150 private static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100;
Kenny Rootd2d29252011-08-08 11:27:57 -0700151
Svet Ganova3c4eb32017-04-19 23:51:33 -0700152 private static final String PROPERTY_CHILD_PACKAGES_ENABLED =
153 "persist.sys.child_packages_enabled";
154
Jeff Sharkey3f1790d2017-04-25 18:56:17 -0600155 private static final boolean MULTI_PACKAGE_APK_ENABLED = Build.IS_DEBUGGABLE &&
Garrett Boyer17041532017-08-01 14:11:02 -0700156 SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false);
Svet Ganova3c4eb32017-04-19 23:51:33 -0700157
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700158 private static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f;
159
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700160 // TODO: switch outError users to PackageParserException
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700161 // TODO: refactor "codePath" to "apkPath"
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700162
Kenny Rootbcc954d2011-08-08 16:19:08 -0700163 /** File name in an APK for the Android manifest. */
Dan Cashmane92f8422017-12-08 14:02:51 -0800164 public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
Kenny Rootbcc954d2011-08-08 16:19:08 -0700165
Jeff Sharkeyb9f36742015-04-08 21:02:14 -0700166 /** Path prefix for apps on expanded storage */
167 private static final String MNT_EXPAND = "/mnt/expand/";
168
Svet Ganov354cd3c2015-12-17 11:35:04 -0800169 private static final String TAG_MANIFEST = "manifest";
170 private static final String TAG_APPLICATION = "application";
Adam Lesinski4e862812016-11-21 16:02:24 -0800171 private static final String TAG_PACKAGE_VERIFIER = "package-verifier";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800172 private static final String TAG_OVERLAY = "overlay";
173 private static final String TAG_KEY_SETS = "key-sets";
174 private static final String TAG_PERMISSION_GROUP = "permission-group";
175 private static final String TAG_PERMISSION = "permission";
176 private static final String TAG_PERMISSION_TREE = "permission-tree";
177 private static final String TAG_USES_PERMISSION = "uses-permission";
178 private static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
179 private static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23";
180 private static final String TAG_USES_CONFIGURATION = "uses-configuration";
181 private static final String TAG_USES_FEATURE = "uses-feature";
182 private static final String TAG_FEATURE_GROUP = "feature-group";
183 private static final String TAG_USES_SDK = "uses-sdk";
184 private static final String TAG_SUPPORT_SCREENS = "supports-screens";
185 private static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
186 private static final String TAG_INSTRUMENTATION = "instrumentation";
187 private static final String TAG_ORIGINAL_PACKAGE = "original-package";
188 private static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
189 private static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
190 private static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
191 private static final String TAG_SUPPORTS_INPUT = "supports-input";
192 private static final String TAG_EAT_COMMENT = "eat-comment";
193 private static final String TAG_PACKAGE = "package";
Todd Kennedyfdd241a2016-04-28 12:26:53 -0700194 private static final String TAG_RESTRICT_UPDATE = "restrict-update";
Adam Lesinski4e862812016-11-21 16:02:24 -0800195 private static final String TAG_USES_SPLIT = "uses-split";
Svet Ganov354cd3c2015-12-17 11:35:04 -0800196
Todd Kennedyfe7f38c32017-03-23 09:51:21 -0700197 // [b/36551762] STOPSHIP remove the ability to expose components via meta-data
Todd Kennedy752fb702017-03-21 16:28:10 -0700198 // Temporary workaround; allow meta-data to expose components to instant apps
199 private static final String META_DATA_INSTANT_APPS = "instantapps.clients.allowed";
200
Bryce Lee22571db2017-07-07 15:54:18 -0700201 private static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
202
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800203 /**
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700204 * Bit mask of all the valid bits that can be set in recreateOnConfigChanges.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800205 * @hide
206 */
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700207 private static final int RECREATE_ON_CONFIG_CHANGES_MASK =
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800208 ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC;
209
Svet Ganov354cd3c2015-12-17 11:35:04 -0800210 // These are the tags supported by child packages
211 private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>();
212 static {
213 CHILD_PACKAGE_TAGS.add(TAG_APPLICATION);
214 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION);
215 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_M);
216 CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_23);
217 CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION);
218 CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE);
219 CHILD_PACKAGE_TAGS.add(TAG_FEATURE_GROUP);
220 CHILD_PACKAGE_TAGS.add(TAG_USES_SDK);
221 CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS);
222 CHILD_PACKAGE_TAGS.add(TAG_INSTRUMENTATION);
223 CHILD_PACKAGE_TAGS.add(TAG_USES_GL_TEXTURE);
224 CHILD_PACKAGE_TAGS.add(TAG_COMPATIBLE_SCREENS);
225 CHILD_PACKAGE_TAGS.add(TAG_SUPPORTS_INPUT);
226 CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
227 }
228
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700229 private static final boolean LOG_UNSAFE_BROADCASTS = false;
230
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700231 /**
232 * Total number of packages that were read from the cache. We use it only for logging.
233 */
234 public static final AtomicInteger sCachedPackageReadCount = new AtomicInteger();
235
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -0700236 // Set of broadcast actions that are safe for manifest receivers
237 private static final Set<String> SAFE_BROADCASTS = new ArraySet<>();
238 static {
239 SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED);
240 }
241
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700242 /** @hide */
Calin Juravle3fc56c32017-12-11 18:26:13 -0800243 public static final String APK_FILE_EXTENSION = ".apk";
244
245 /** @hide */
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700246 public static class NewPermissionInfo {
247 public final String name;
248 public final int sdkVersion;
249 public final int fileVersion;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700250
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700251 public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
252 this.name = name;
253 this.sdkVersion = sdkVersion;
254 this.fileVersion = fileVersion;
255 }
256 }
Dianne Hackborn79245122012-03-12 10:51:26 -0700257
258 /** @hide */
259 public static class SplitPermissionInfo {
260 public final String rootPerm;
261 public final String[] newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700262 public final int targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700263
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700264 public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
Dianne Hackborn79245122012-03-12 10:51:26 -0700265 this.rootPerm = rootPerm;
266 this.newPerms = newPerms;
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700267 this.targetSdk = targetSdk;
Dianne Hackborn79245122012-03-12 10:51:26 -0700268 }
269 }
270
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700271 /**
272 * List of new permissions that have been added since 1.0.
273 * NOTE: These must be declared in SDK version order, with permissions
274 * added to older SDKs appearing before those added to newer SDKs.
Dianne Hackborn79245122012-03-12 10:51:26 -0700275 * If sdkVersion is 0, then this is not a permission that we want to
276 * automatically add to older apps, but we do want to allow it to be
277 * granted during a platform update.
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700278 * @hide
279 */
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700280 public static final PackageParser.NewPermissionInfo NEW_PERMISSIONS[] =
281 new PackageParser.NewPermissionInfo[] {
San Mehat5a3a77d2009-06-01 09:25:28 -0700282 new PackageParser.NewPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700283 android.os.Build.VERSION_CODES.DONUT, 0),
284 new PackageParser.NewPermissionInfo(android.Manifest.permission.READ_PHONE_STATE,
285 android.os.Build.VERSION_CODES.DONUT, 0)
Dianne Hackborna96cbb42009-05-13 15:06:13 -0700286 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287
Dianne Hackborn79245122012-03-12 10:51:26 -0700288 /**
289 * List of permissions that have been split into more granular or dependent
290 * permissions.
291 * @hide
292 */
293 public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
294 new PackageParser.SplitPermissionInfo[] {
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700295 // READ_EXTERNAL_STORAGE is always required when an app requests
296 // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
297 // write access without read access. The hack here with the target
298 // target SDK version ensures that this grant is always done.
Dianne Hackborn79245122012-03-12 10:51:26 -0700299 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700300 new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
Dianne Hackborn2bd8d042012-06-11 12:27:05 -0700301 android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -0700302 new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
303 new String[] { android.Manifest.permission.READ_CALL_LOG },
304 android.os.Build.VERSION_CODES.JELLY_BEAN),
305 new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
306 new String[] { android.Manifest.permission.WRITE_CALL_LOG },
307 android.os.Build.VERSION_CODES.JELLY_BEAN)
Dianne Hackborn79245122012-03-12 10:51:26 -0700308 };
309
Jeff Sharkey275e0852014-06-17 18:18:49 -0700310 /**
311 * @deprecated callers should move to explicitly passing around source path.
312 */
313 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 private String mArchiveSourcePath;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 private String[] mSeparateProcesses;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700317 private boolean mOnlyCoreApps;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700318 private DisplayMetrics mMetrics;
Dianne Hackborncd154e92017-02-28 17:37:35 -0800319 private Callback mCallback;
Narayan Kamath988149c2016-12-01 13:32:59 +0000320 private File mCacheDir;
Jeff Sharkey275e0852014-06-17 18:18:49 -0700321
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -0700322 private static final int SDK_VERSION = Build.VERSION.SDK_INT;
Dianne Hackbornffcda102014-04-24 13:06:27 -0700323 private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324
325 private int mParseError = PackageManager.INSTALL_SUCCEEDED;
326
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -0700327 private static boolean sCompatibilityModeEnabled = true;
Amith Yamasani655d0e22013-06-12 14:19:10 -0700328 private static final int PARSE_DEFAULT_INSTALL_LOCATION =
329 PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
Todd Kennedy11e45072017-01-25 13:24:21 -0800330 private static final int PARSE_DEFAULT_TARGET_SANDBOX = 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700331
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700332 static class ParsePackageItemArgs {
333 final Package owner;
334 final String[] outError;
335 final int nameRes;
336 final int labelRes;
337 final int iconRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700338 final int roundIconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700339 final int logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800340 final int bannerRes;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700341
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700342 String tag;
343 TypedArray sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700344
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700345 ParsePackageItemArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700346 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
347 int _bannerRes) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700348 owner = _owner;
349 outError = _outError;
350 nameRes = _nameRes;
351 labelRes = _labelRes;
352 iconRes = _iconRes;
Adam Powell81cd2e92010-04-21 16:35:18 -0700353 logoRes = _logoRes;
Jose Limaf78e3122014-03-06 12:13:15 -0800354 bannerRes = _bannerRes;
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700355 roundIconRes = _roundIconRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700356 }
357 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700358
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000359 /** @hide */
360 @VisibleForTesting
361 public static class ParseComponentArgs extends ParsePackageItemArgs {
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700362 final String[] sepProcesses;
363 final int processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800364 final int descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700365 final int enabledRes;
366 int flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700367
Narayan Kamathfb2afbf2016-11-24 13:22:40 +0000368 public ParseComponentArgs(Package _owner, String[] _outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700369 int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
370 int _bannerRes,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800371 String[] _sepProcesses, int _processRes,
372 int _descriptionRes, int _enabledRes) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -0700373 super(_owner, _outError, _nameRes, _labelRes, _iconRes, _roundIconRes, _logoRes,
374 _bannerRes);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700375 sepProcesses = _sepProcesses;
376 processRes = _processRes;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800377 descriptionRes = _descriptionRes;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700378 enabledRes = _enabledRes;
379 }
380 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800381
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700382 /**
Jeff Sharkey73767b92014-07-04 20:18:13 -0700383 * Lightweight parsed details about a single package.
384 */
385 public static class PackageLite {
386 public final String packageName;
387 public final int versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700388 public final int versionCodeMajor;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700389 public final int installLocation;
390 public final VerifierInfo[] verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700391
392 /** Names of any split APKs, ordered by parsed splitName */
393 public final String[] splitNames;
394
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800395 /** Names of any split APKs that are features. Ordered by splitName */
396 public final boolean[] isFeatureSplits;
397
Adam Lesinski4e862812016-11-21 16:02:24 -0800398 /** Dependencies of any split APKs, ordered by parsed splitName */
399 public final String[] usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800400 public final String[] configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800401
Jeff Sharkey73767b92014-07-04 20:18:13 -0700402 /**
403 * Path where this package was found on disk. For monolithic packages
404 * this is path to single base APK file; for cluster packages this is
405 * path to the cluster directory.
406 */
407 public final String codePath;
408
409 /** Path of base APK */
410 public final String baseCodePath;
411 /** Paths of any split APKs, ordered by parsed splitName */
412 public final String[] splitCodePaths;
413
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800414 /** Revision code of base APK */
415 public final int baseRevisionCode;
416 /** Revision codes of any split APKs, ordered by parsed splitName */
417 public final int[] splitRevisionCodes;
418
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700419 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100420 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100421 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800422 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700423 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800424 public final boolean isolatedSplits;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100425
Jeff Sharkey941a8ba2014-08-20 16:26:32 -0700426 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800427 boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100428 String[] splitCodePaths, int[] splitRevisionCodes) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700429 this.packageName = baseApk.packageName;
430 this.versionCode = baseApk.versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700431 this.versionCodeMajor = baseApk.versionCodeMajor;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700432 this.installLocation = baseApk.installLocation;
433 this.verifiers = baseApk.verifiers;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700434 this.splitNames = splitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800435 this.isFeatureSplits = isFeatureSplits;
Adam Lesinski4e862812016-11-21 16:02:24 -0800436 this.usesSplitNames = usesSplitNames;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800437 this.configForSplit = configForSplit;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700438 this.codePath = codePath;
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700439 this.baseCodePath = baseApk.codePath;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700440 this.splitCodePaths = splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800441 this.baseRevisionCode = baseApk.revisionCode;
442 this.splitRevisionCodes = splitRevisionCodes;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700443 this.coreApp = baseApk.coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100444 this.debuggable = baseApk.debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100445 this.multiArch = baseApk.multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800446 this.use32bitAbi = baseApk.use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700447 this.extractNativeLibs = baseApk.extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800448 this.isolatedSplits = baseApk.isolatedSplits;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700449 }
450
451 public List<String> getAllCodePaths() {
452 ArrayList<String> paths = new ArrayList<>();
453 paths.add(baseCodePath);
454 if (!ArrayUtils.isEmpty(splitCodePaths)) {
455 Collections.addAll(paths, splitCodePaths);
456 }
457 return paths;
458 }
459 }
460
461 /**
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700462 * Lightweight parsed details about a single APK file.
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800463 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700464 public static class ApkLite {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700465 public final String codePath;
Kenny Root05ca4c92011-09-15 10:36:25 -0700466 public final String packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700467 public final String splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800468 public boolean isFeatureSplit;
469 public final String configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800470 public final String usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700471 public final int versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700472 public final int versionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800473 public final int revisionCode;
Kenny Root05ca4c92011-09-15 10:36:25 -0700474 public final int installLocation;
475 public final VerifierInfo[] verifiers;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800476 public final SigningDetails signingDetails;
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700477 public final boolean coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100478 public final boolean debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100479 public final boolean multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800480 public final boolean use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700481 public final boolean extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800482 public final boolean isolatedSplits;
Kenny Root05ca4c92011-09-15 10:36:25 -0700483
Patrick Baumann47117fc2017-12-19 10:17:21 -0800484 public ApkLite(String codePath, String packageName, String splitName,
485 boolean isFeatureSplit,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700486 String configForSplit, String usesSplitName, int versionCode, int versionCodeMajor,
487 int revisionCode, int installLocation, List<VerifierInfo> verifiers,
Patrick Baumann47117fc2017-12-19 10:17:21 -0800488 SigningDetails signingDetails, boolean coreApp,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700489 boolean debuggable, boolean multiArch, boolean use32bitAbi,
490 boolean extractNativeLibs, boolean isolatedSplits) {
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700491 this.codePath = codePath;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800492 this.packageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700493 this.splitName = splitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800494 this.isFeatureSplit = isFeatureSplit;
495 this.configForSplit = configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800496 this.usesSplitName = usesSplitName;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700497 this.versionCode = versionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700498 this.versionCodeMajor = versionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800499 this.revisionCode = revisionCode;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800500 this.installLocation = installLocation;
Patrick Baumann47117fc2017-12-19 10:17:21 -0800501 this.signingDetails = signingDetails;
Kenny Root05ca4c92011-09-15 10:36:25 -0700502 this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700503 this.coreApp = coreApp;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +0100504 this.debuggable = debuggable;
Narayan Kamathff110bd2014-07-04 18:30:45 +0100505 this.multiArch = multiArch;
Selim Gurun2d291d82016-02-05 17:50:53 -0800506 this.use32bitAbi = use32bitAbi;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -0700507 this.extractNativeLibs = extractNativeLibs;
Adam Lesinski4e862812016-11-21 16:02:24 -0800508 this.isolatedSplits = isolatedSplits;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800509 }
Dianne Hackborn3accca02013-09-20 09:32:11 -0700510
511 public long getLongVersionCode() {
512 return PackageInfo.composeLongVersionCode(versionCodeMajor, versionCode);
513 }
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -0800514 }
515
Garrett Boyer52136662017-05-23 13:47:58 -0700516 /**
517 * Cached parse state for new components.
518 *
519 * Allows reuse of the same parse argument records to avoid GC pressure. Lifetime is carefully
520 * scoped to the parsing of a single application element.
521 */
522 private static class CachedComponentArgs {
523 ParseComponentArgs mActivityArgs;
524 ParseComponentArgs mActivityAliasArgs;
525 ParseComponentArgs mServiceArgs;
526 ParseComponentArgs mProviderArgs;
527 }
528
529 /**
530 * Cached state for parsing instrumentation to avoid GC pressure.
531 *
532 * Must be manually reset to null for each new manifest.
533 */
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700534 private ParsePackageItemArgs mParseInstrumentationArgs;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -0700535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 /** If set to true, we will only allow package files that exactly match
537 * the DTD. Otherwise, we try to get as much from the package as we
538 * can without failing. This should normally be set to false, to
539 * support extensions to the DTD in future versions. */
540 private static final boolean RIGID_PARSER = false;
541
542 private static final String TAG = "PackageParser";
543
Jeff Sharkey275e0852014-06-17 18:18:49 -0700544 public PackageParser() {
545 mMetrics = new DisplayMetrics();
546 mMetrics.setToDefaults();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700547 }
548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 public void setSeparateProcesses(String[] procs) {
550 mSeparateProcesses = procs;
551 }
552
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700553 /**
554 * Flag indicating this parser should only consider apps with
555 * {@code coreApp} manifest attribute to be valid apps. This is useful when
556 * creating a minimalist boot environment.
557 */
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700558 public void setOnlyCoreApps(boolean onlyCoreApps) {
559 mOnlyCoreApps = onlyCoreApps;
560 }
561
Jeff Sharkey275e0852014-06-17 18:18:49 -0700562 public void setDisplayMetrics(DisplayMetrics metrics) {
563 mMetrics = metrics;
564 }
565
Narayan Kamath988149c2016-12-01 13:32:59 +0000566 /**
567 * Sets the cache directory for this package parser.
568 */
569 public void setCacheDir(File cacheDir) {
570 mCacheDir = cacheDir;
571 }
572
Dianne Hackborncd154e92017-02-28 17:37:35 -0800573 /**
574 * Callback interface for retrieving information that may be needed while parsing
575 * a package.
576 */
577 public interface Callback {
578 boolean hasFeature(String feature);
Jaekyun Seok30dc2a02017-04-11 09:41:11 +0900579 String[] getOverlayPaths(String targetPackageName, String targetPath);
580 String[] getOverlayApks(String targetPackageName);
Dianne Hackborncd154e92017-02-28 17:37:35 -0800581 }
582
583 /**
584 * Standard implementation of {@link Callback} on top of the public {@link PackageManager}
585 * class.
586 */
587 public static final class CallbackImpl implements Callback {
588 private final PackageManager mPm;
589
590 public CallbackImpl(PackageManager pm) {
591 mPm = pm;
592 }
593
594 @Override public boolean hasFeature(String feature) {
595 return mPm.hasSystemFeature(feature);
596 }
Jaekyun Seok30dc2a02017-04-11 09:41:11 +0900597
598 @Override public String[] getOverlayPaths(String targetPackageName, String targetPath) {
599 return null;
600 }
601
602 @Override public String[] getOverlayApks(String targetPackageName) {
603 return null;
604 }
Dianne Hackborncd154e92017-02-28 17:37:35 -0800605 }
606
607 /**
608 * Set the {@link Callback} that can be used while parsing.
609 */
610 public void setCallback(Callback cb) {
611 mCallback = cb;
612 }
613
Jeff Sharkey73767b92014-07-04 20:18:13 -0700614 public static final boolean isApkFile(File file) {
Adam Lesinski3bcbd902014-08-22 17:01:04 -0700615 return isApkPath(file.getName());
616 }
617
Adam Lesinski4e862812016-11-21 16:02:24 -0800618 public static boolean isApkPath(String path) {
Calin Juravle3fc56c32017-12-11 18:26:13 -0800619 return path.endsWith(APK_FILE_EXTENSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800620 }
621
622 /**
623 * Generate and return the {@link PackageInfo} for a parsed package.
624 *
625 * @param p the parsed package.
626 * @param flags indicating which optional information is included.
627 */
628 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Dianne Hackborne639da72012-02-21 15:11:13 -0800629 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svet Ganov3695b8a2015-03-24 16:30:25 -0700630 Set<String> grantedPermissions, PackageUserState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631
Amith Yamasani483f3b02012-03-13 16:08:00 -0700632 return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700633 grantedPermissions, state, UserHandle.getCallingUserId());
634 }
635
Amith Yamasani655d0e22013-06-12 14:19:10 -0700636 /**
Amith Yamasanie5bcff62014-07-19 15:44:09 -0700637 * Returns true if the package is installed and not hidden, or if the caller
638 * explicitly wanted all uninstalled and hidden packages as well.
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700639 * @param appInfo The applicationInfo of the app being checked.
Amith Yamasani655d0e22013-06-12 14:19:10 -0700640 */
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700641 private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state,
642 ApplicationInfo appInfo) {
643 // If available for the target user, or trying to match uninstalled packages and it's
644 // a system app.
645 return state.isAvailable(flags)
646 || (appInfo != null && appInfo.isSystemApp()
647 && (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0);
Amith Yamasani483f3b02012-03-13 16:08:00 -0700648 }
649
Christopher Tateba629da2013-11-13 17:42:28 -0800650 public static boolean isAvailable(PackageUserState state) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700651 return checkUseInstalledOrHidden(0, state, null);
Christopher Tateba629da2013-11-13 17:42:28 -0800652 }
653
Amith Yamasani13593602012-03-22 16:16:17 -0700654 public static PackageInfo generatePackageInfo(PackageParser.Package p,
Amith Yamasani483f3b02012-03-13 16:08:00 -0700655 int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Svetoslavc6d1c342015-02-26 14:44:43 -0800656 Set<String> grantedPermissions, PackageUserState state, int userId) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700657 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700658 return null;
659 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800660 PackageInfo pi = new PackageInfo();
661 pi.packageName = p.packageName;
Jeff Sharkey6c833e02014-07-14 22:44:30 -0700662 pi.splitNames = p.splitNames;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663 pi.versionCode = p.mVersionCode;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700664 pi.versionCodeMajor = p.mVersionCodeMajor;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800665 pi.baseRevisionCode = p.baseRevisionCode;
666 pi.splitRevisionCodes = p.splitRevisionCodes;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667 pi.versionName = p.mVersionName;
668 pi.sharedUserId = p.mSharedUserId;
669 pi.sharedUserLabel = p.mSharedUserLabel;
Dianne Hackborn7767eac2012-08-23 18:25:40 -0700670 pi.applicationInfo = generateApplicationInfo(p, flags, state, userId);
Suchi Amalapurapu117818e2010-02-09 03:45:40 -0800671 pi.installLocation = p.installLocation;
Todd Kennedy7c8addf2017-06-27 14:13:55 -0700672 pi.isStub = p.isStub;
Jeff Hao272bf3a2014-10-08 13:34:43 -0700673 pi.coreApp = p.coreApp;
Amith Yamasani0d8750d2013-05-01 15:25:28 -0700674 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
675 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
676 pi.requiredForAllUsers = p.mRequiredForAllUsers;
677 }
Amith Yamasani0ac1fc92013-03-27 18:56:08 -0700678 pi.restrictedAccountType = p.mRestrictedAccountType;
Amith Yamasaniccbe3892013-04-12 17:52:42 -0700679 pi.requiredAccountType = p.mRequiredAccountType;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +0100680 pi.overlayTarget = p.mOverlayTarget;
Jaekyun Seok42d53f62017-04-10 13:48:58 +0900681 pi.overlayPriority = p.mOverlayPriority;
Adam Lesinskiab56b9d2017-11-14 00:50:18 -0800682
683 if (p.mIsStaticOverlay) {
684 pi.mOverlayFlags |= PackageInfo.FLAG_OVERLAY_STATIC;
685 }
686
687 if (p.mTrustedOverlay) {
688 pi.mOverlayFlags |= PackageInfo.FLAG_OVERLAY_TRUSTED;
689 }
690
Alan Viveretteb6a25732017-11-21 14:49:24 -0500691 pi.compileSdkVersion = p.mCompileSdkVersion;
692 pi.compileSdkVersionCodename = p.mCompileSdkVersionCodename;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700693 pi.firstInstallTime = firstInstallTime;
694 pi.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695 if ((flags&PackageManager.GET_GIDS) != 0) {
696 pi.gids = gids;
697 }
698 if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700699 int N = p.configPreferences != null ? p.configPreferences.size() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700 if (N > 0) {
701 pi.configPreferences = new ConfigurationInfo[N];
Dianne Hackborn49237342009-08-27 20:08:01 -0700702 p.configPreferences.toArray(pi.configPreferences);
703 }
704 N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
705 if (N > 0) {
706 pi.reqFeatures = new FeatureInfo[N];
707 p.reqFeatures.toArray(pi.reqFeatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 }
Adam Lesinskid3edfde2014-08-08 17:32:44 -0700709 N = p.featureGroups != null ? p.featureGroups.size() : 0;
710 if (N > 0) {
711 pi.featureGroups = new FeatureGroupInfo[N];
712 p.featureGroups.toArray(pi.featureGroups);
713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800714 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700715 if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
716 final int N = p.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800717 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700718 int num = 0;
719 final ActivityInfo[] res = new ActivityInfo[N];
720 for (int i = 0; i < N; i++) {
721 final Activity a = p.activities.get(i);
722 if (state.isMatch(a.info, flags)) {
723 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800724 }
725 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700726 pi.activities = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 }
728 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700729 if ((flags & PackageManager.GET_RECEIVERS) != 0) {
730 final int N = p.receivers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800731 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700732 int num = 0;
733 final ActivityInfo[] res = new ActivityInfo[N];
734 for (int i = 0; i < N; i++) {
735 final Activity a = p.receivers.get(i);
736 if (state.isMatch(a.info, flags)) {
737 res[num++] = generateActivityInfo(a, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 }
739 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700740 pi.receivers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800741 }
742 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700743 if ((flags & PackageManager.GET_SERVICES) != 0) {
744 final int N = p.services.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800745 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700746 int num = 0;
747 final ServiceInfo[] res = new ServiceInfo[N];
748 for (int i = 0; i < N; i++) {
749 final Service s = p.services.get(i);
750 if (state.isMatch(s.info, flags)) {
751 res[num++] = generateServiceInfo(s, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752 }
753 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700754 pi.services = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 }
756 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700757 if ((flags & PackageManager.GET_PROVIDERS) != 0) {
758 final int N = p.providers.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 if (N > 0) {
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700760 int num = 0;
761 final ProviderInfo[] res = new ProviderInfo[N];
762 for (int i = 0; i < N; i++) {
763 final Provider pr = p.providers.get(i);
764 if (state.isMatch(pr.info, flags)) {
765 res[num++] = generateProviderInfo(pr, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 }
767 }
Jeff Sharkey2bd31db2016-01-09 16:58:14 -0700768 pi.providers = ArrayUtils.trimToSize(res, num);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769 }
770 }
771 if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
772 int N = p.instrumentation.size();
773 if (N > 0) {
774 pi.instrumentation = new InstrumentationInfo[N];
775 for (int i=0; i<N; i++) {
776 pi.instrumentation[i] = generateInstrumentationInfo(
777 p.instrumentation.get(i), flags);
778 }
779 }
780 }
781 if ((flags&PackageManager.GET_PERMISSIONS) != 0) {
782 int N = p.permissions.size();
783 if (N > 0) {
784 pi.permissions = new PermissionInfo[N];
785 for (int i=0; i<N; i++) {
786 pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
787 }
788 }
789 N = p.requestedPermissions.size();
790 if (N > 0) {
791 pi.requestedPermissions = new String[N];
Dianne Hackborne639da72012-02-21 15:11:13 -0800792 pi.requestedPermissionsFlags = new int[N];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793 for (int i=0; i<N; i++) {
Dianne Hackborne639da72012-02-21 15:11:13 -0800794 final String perm = p.requestedPermissions.get(i);
795 pi.requestedPermissions[i] = perm;
Svet Ganov3695b8a2015-03-24 16:30:25 -0700796 // The notion of required permissions is deprecated but for compatibility.
Svetoslavc6d1c342015-02-26 14:44:43 -0800797 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
Dianne Hackborne639da72012-02-21 15:11:13 -0800798 if (grantedPermissions != null && grantedPermissions.contains(perm)) {
799 pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
800 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 }
802 }
803 }
Daniel Cashman5cdda342018-01-19 07:22:52 -0800804 // deprecated method of getting signing certificates
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 if ((flags&PackageManager.GET_SIGNATURES) != 0) {
Daniel Cashman5cdda342018-01-19 07:22:52 -0800806 if (p.mSigningDetails.hasPastSigningCertificates()) {
807 // Package has included signing certificate rotation information. Return the oldest
808 // cert so that programmatic checks keep working even if unaware of key rotation.
809 pi.signatures = new Signature[1];
810 pi.signatures[0] = p.mSigningDetails.pastSigningCertificates[0];
811 } else if (p.mSigningDetails.hasSignatures()) {
812 // otherwise keep old behavior
Patrick Baumann47117fc2017-12-19 10:17:21 -0800813 int numberOfSigs = p.mSigningDetails.signatures.length;
814 pi.signatures = new Signature[numberOfSigs];
815 System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 }
817 }
Daniel Cashman5cdda342018-01-19 07:22:52 -0800818
819 // replacement for GET_SIGNATURES
820 if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
821 if (p.mSigningDetails.hasPastSigningCertificates()) {
822 // Package has included signing certificate rotation information. Convert each
823 // entry to an array
824 int numberOfSigs = p.mSigningDetails.pastSigningCertificates.length;
825 pi.signingCertificateHistory = new Signature[numberOfSigs][];
826 for (int i = 0; i < numberOfSigs; i++) {
827 pi.signingCertificateHistory[i] =
828 new Signature[] { p.mSigningDetails.pastSigningCertificates[i] };
829 }
830 } else if (p.mSigningDetails.hasSignatures()) {
831 // otherwise keep old behavior
832 int numberOfSigs = p.mSigningDetails.signatures.length;
833 pi.signingCertificateHistory = new Signature[1][numberOfSigs];
834 System.arraycopy(p.mSigningDetails.signatures, 0,
835 pi.signingCertificateHistory[0], 0, numberOfSigs);
836 }
837 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800838 return pi;
839 }
840
Todd Kennedy232d29e2017-11-06 14:45:53 -0800841 public static final int PARSE_MUST_BE_APK = 1 << 0;
842 public static final int PARSE_IGNORE_PROCESSES = 1 << 1;
Todd Kennedy30a23a52018-01-04 13:27:49 -0800843 /** @deprecated forward lock no longer functional. remove. */
844 @Deprecated
Todd Kennedy232d29e2017-11-06 14:45:53 -0800845 public static final int PARSE_FORWARD_LOCK = 1 << 2;
846 public static final int PARSE_EXTERNAL_STORAGE = 1 << 3;
847 public static final int PARSE_IS_SYSTEM_DIR = 1 << 4;
848 public static final int PARSE_COLLECT_CERTIFICATES = 1 << 5;
849 public static final int PARSE_ENFORCE_CODE = 1 << 6;
850 public static final int PARSE_FORCE_SDK = 1 << 7;
Todd Kennedy232d29e2017-11-06 14:45:53 -0800851 public static final int PARSE_CHATTY = 1 << 31;
852
853 @IntDef(flag = true, prefix = { "PARSE_" }, value = {
854 PARSE_CHATTY,
855 PARSE_COLLECT_CERTIFICATES,
856 PARSE_ENFORCE_CODE,
857 PARSE_EXTERNAL_STORAGE,
858 PARSE_FORCE_SDK,
859 PARSE_FORWARD_LOCK,
860 PARSE_IGNORE_PROCESSES,
Todd Kennedy232d29e2017-11-06 14:45:53 -0800861 PARSE_IS_SYSTEM_DIR,
862 PARSE_MUST_BE_APK,
863 })
864 @Retention(RetentionPolicy.SOURCE)
865 public @interface ParseFlags {}
Jeff Sharkey275e0852014-06-17 18:18:49 -0700866
867 private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800868
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700869 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -0700870 * Used to sort a set of APKs based on their split names, always placing the
871 * base APK (with {@code null} split name) first.
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700872 */
Jeff Sharkey275e0852014-06-17 18:18:49 -0700873 private static class SplitNameComparator implements Comparator<String> {
874 @Override
875 public int compare(String lhs, String rhs) {
876 if (lhs == null) {
877 return -1;
878 } else if (rhs == null) {
879 return 1;
880 } else {
881 return lhs.compareTo(rhs);
882 }
883 }
884 }
885
Jeff Sharkeyda96e132014-07-15 14:54:09 -0700886 /**
887 * Parse only lightweight details about the package at the given location.
888 * Automatically detects if the package is a monolithic style (single APK
889 * file) or cluster style (directory of APKs).
890 * <p>
891 * This performs sanity checking on cluster style packages, such as
892 * requiring identical package name and version codes, a single base APK,
893 * and unique split names.
894 *
895 * @see PackageParser#parsePackage(File, int)
896 */
Jeff Sharkey73767b92014-07-04 20:18:13 -0700897 public static PackageLite parsePackageLite(File packageFile, int flags)
898 throws PackageParserException {
899 if (packageFile.isDirectory()) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800900 return parseClusterPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700901 } else {
Adam Lesinski4e862812016-11-21 16:02:24 -0800902 return parseMonolithicPackageLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700903 }
904 }
905
Adam Lesinski4e862812016-11-21 16:02:24 -0800906 private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
907 throws PackageParserException {
Todd Kennedycd029da2016-07-21 07:41:09 -0700908 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Adam Lesinski4e862812016-11-21 16:02:24 -0800909 final ApkLite baseApk = parseApkLite(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700910 final String packagePath = packageFile.getAbsolutePath();
Todd Kennedycd029da2016-07-21 07:41:09 -0700911 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Narayan Kamath96c11c52017-08-09 13:07:21 +0100912 return new PackageLite(packagePath, baseApk, null, null, null, null, null, null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700913 }
914
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800915 static PackageLite parseClusterPackageLite(File packageDir, int flags)
Adam Lesinski4e862812016-11-21 16:02:24 -0800916 throws PackageParserException {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700917 final File[] files = packageDir.listFiles();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700918 if (ArrayUtils.isEmpty(files)) {
919 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
920 "No packages found in split");
921 }
922
Jeff Sharkey275e0852014-06-17 18:18:49 -0700923 String packageName = null;
924 int versionCode = 0;
925
Todd Kennedycd029da2016-07-21 07:41:09 -0700926 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700927 final ArrayMap<String, ApkLite> apks = new ArrayMap<>();
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700928 for (File file : files) {
Jeff Sharkey73767b92014-07-04 20:18:13 -0700929 if (isApkFile(file)) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800930 final ApkLite lite = parseApkLite(file, flags);
Jeff Sharkey275e0852014-06-17 18:18:49 -0700931
932 // Assert that all package names and version codes are
933 // consistent with the first one we encounter.
934 if (packageName == null) {
935 packageName = lite.packageName;
936 versionCode = lite.versionCode;
937 } else {
938 if (!packageName.equals(lite.packageName)) {
939 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
940 "Inconsistent package " + lite.packageName + " in " + file
941 + "; expected " + packageName);
942 }
943 if (versionCode != lite.versionCode) {
944 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
945 "Inconsistent version " + lite.versionCode + " in " + file
946 + "; expected " + versionCode);
947 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700948 }
949
Jeff Sharkey275e0852014-06-17 18:18:49 -0700950 // Assert that each split is defined only once
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700951 if (apks.put(lite.splitName, lite) != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700952 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
953 "Split name " + lite.splitName
954 + " defined more than once; most recent was " + file);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700955 }
956 }
957 }
Todd Kennedycd029da2016-07-21 07:41:09 -0700958 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700959
Jeff Sharkeybe520fb2014-07-04 18:23:17 -0700960 final ApkLite baseApk = apks.remove(null);
Jeff Sharkey73767b92014-07-04 20:18:13 -0700961 if (baseApk == null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -0700962 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
Jeff Sharkey73767b92014-07-04 20:18:13 -0700963 "Missing base APK in " + packageDir);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700964 }
965
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700966 // Always apply deterministic ordering based on splitName
967 final int size = apks.size();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -0700968
Jeff Sharkey73767b92014-07-04 20:18:13 -0700969 String[] splitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800970 boolean[] isFeatureSplits = null;
Adam Lesinski4e862812016-11-21 16:02:24 -0800971 String[] usesSplitNames = null;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800972 String[] configForSplits = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700973 String[] splitCodePaths = null;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800974 int[] splitRevisionCodes = null;
Narayan Kamathf9419f02017-06-15 11:35:38 +0100975 String[] splitClassLoaderNames = null;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700976 if (size > 0) {
977 splitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800978 isFeatureSplits = new boolean[size];
Adam Lesinski4e862812016-11-21 16:02:24 -0800979 usesSplitNames = new String[size];
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800980 configForSplits = new String[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700981 splitCodePaths = new String[size];
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -0800982 splitRevisionCodes = new int[size];
Jeff Sharkey73767b92014-07-04 20:18:13 -0700983
984 splitNames = apks.keySet().toArray(splitNames);
985 Arrays.sort(splitNames, sSplitNameComparator);
986
987 for (int i = 0; i < size; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -0800988 final ApkLite apk = apks.get(splitNames[i]);
989 usesSplitNames[i] = apk.usesSplitName;
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800990 isFeatureSplits[i] = apk.isFeatureSplit;
991 configForSplits[i] = apk.configForSplit;
Adam Lesinski4e862812016-11-21 16:02:24 -0800992 splitCodePaths[i] = apk.codePath;
993 splitRevisionCodes[i] = apk.revisionCode;
Jeff Sharkey73767b92014-07-04 20:18:13 -0700994 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -0700995 }
996
Jeff Sharkey73767b92014-07-04 20:18:13 -0700997 final String codePath = packageDir.getAbsolutePath();
Adam Lesinski1665d0f2017-03-10 14:46:57 -0800998 return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames,
Narayan Kamath96c11c52017-08-09 13:07:21 +0100999 configForSplits, splitCodePaths, splitRevisionCodes);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001000 }
1001
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001002 /**
1003 * Parse the package at the given location. Automatically detects if the
1004 * package is a monolithic style (single APK file) or cluster style
1005 * (directory of APKs).
1006 * <p>
1007 * This performs sanity checking on cluster style packages, such as
1008 * requiring identical package name and version codes, a single base APK,
1009 * and unique split names.
1010 * <p>
1011 * Note that this <em>does not</em> perform signature verification; that
1012 * must be done separately in {@link #collectCertificates(Package, int)}.
1013 *
Narayan Kamath988149c2016-12-01 13:32:59 +00001014 * If {@code useCaches} is true, the package parser might return a cached
1015 * result from a previous parse of the same {@code packageFile} with the same
1016 * {@code flags}. Note that this method does not check whether {@code packageFile}
1017 * has changed since the last parse, it's up to callers to do so.
1018 *
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001019 * @see #parsePackageLite(File, int)
1020 */
Narayan Kamath988149c2016-12-01 13:32:59 +00001021 public Package parsePackage(File packageFile, int flags, boolean useCaches)
1022 throws PackageParserException {
1023 Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;
1024 if (parsed != null) {
1025 return parsed;
1026 }
1027
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001028 long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Jeff Sharkey73767b92014-07-04 20:18:13 -07001029 if (packageFile.isDirectory()) {
Narayan Kamath988149c2016-12-01 13:32:59 +00001030 parsed = parseClusterPackage(packageFile, flags);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001031 } else {
Narayan Kamath988149c2016-12-01 13:32:59 +00001032 parsed = parseMonolithicPackage(packageFile, flags);
1033 }
1034
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001035 long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
Narayan Kamath988149c2016-12-01 13:32:59 +00001036 cacheResult(packageFile, flags, parsed);
Fyodor Kupolov28a988f2017-07-31 18:44:11 -07001037 if (LOG_PARSE_TIMINGS) {
1038 parseTime = cacheTime - parseTime;
1039 cacheTime = SystemClock.uptimeMillis() - cacheTime;
1040 if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) {
1041 Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime
1042 + "ms, update_cache=" + cacheTime + " ms");
1043 }
1044 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001045 return parsed;
1046 }
1047
1048 /**
1049 * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}.
1050 */
1051 public Package parsePackage(File packageFile, int flags) throws PackageParserException {
1052 return parsePackage(packageFile, flags, false /* useCaches */);
1053 }
1054
1055 /**
1056 * Returns the cache key for a specificied {@code packageFile} and {@code flags}.
1057 */
1058 private String getCacheKey(File packageFile, int flags) {
1059 StringBuilder sb = new StringBuilder(packageFile.getName());
1060 sb.append('-');
1061 sb.append(flags);
1062
1063 return sb.toString();
1064 }
1065
1066 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001067 protected Package fromCacheEntry(byte[] bytes) {
1068 return fromCacheEntryStatic(bytes);
1069 }
1070
1071 /** static version of {@link #fromCacheEntry} for unit tests. */
1072 @VisibleForTesting
1073 public static Package fromCacheEntryStatic(byte[] bytes) {
1074 final Parcel p = Parcel.obtain();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001075 p.unmarshall(bytes, 0, bytes.length);
1076 p.setDataPosition(0);
1077
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001078 final ReadHelper helper = new ReadHelper(p);
1079 helper.startAndInstall();
1080
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001081 PackageParser.Package pkg = new PackageParser.Package(p);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001082
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001083 p.recycle();
1084
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001085 sCachedPackageReadCount.incrementAndGet();
1086
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001087 return pkg;
Narayan Kamath988149c2016-12-01 13:32:59 +00001088 }
1089
1090 @VisibleForTesting
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001091 protected byte[] toCacheEntry(Package pkg) {
1092 return toCacheEntryStatic(pkg);
1093
1094 }
1095
1096 /** static version of {@link #toCacheEntry} for unit tests. */
1097 @VisibleForTesting
1098 public static byte[] toCacheEntryStatic(Package pkg) {
1099 final Parcel p = Parcel.obtain();
1100 final WriteHelper helper = new WriteHelper(p);
1101
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001102 pkg.writeToParcel(p, 0 /* flags */);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07001103
1104 helper.finishAndUninstall();
1105
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001106 byte[] serialized = p.marshall();
1107 p.recycle();
1108
1109 return serialized;
Narayan Kamath988149c2016-12-01 13:32:59 +00001110 }
1111
1112 /**
1113 * Given a {@code packageFile} and a {@code cacheFile} returns whether the
1114 * cache file is up to date based on the mod-time of both files.
1115 */
1116 private static boolean isCacheUpToDate(File packageFile, File cacheFile) {
1117 try {
1118 // NOTE: We don't use the File.lastModified API because it has the very
1119 // non-ideal failure mode of returning 0 with no excepions thrown.
1120 // The nio2 Files API is a little better but is considerably more expensive.
1121 final StructStat pkg = android.system.Os.stat(packageFile.getAbsolutePath());
1122 final StructStat cache = android.system.Os.stat(cacheFile.getAbsolutePath());
1123 return pkg.st_mtime < cache.st_mtime;
1124 } catch (ErrnoException ee) {
1125 // The most common reason why stat fails is that a given cache file doesn't
1126 // exist. We ignore that here. It's easy to reason that it's safe to say the
1127 // cache isn't up to date if we see any sort of exception here.
1128 //
1129 // (1) Exception while stating the package file : This should never happen,
1130 // and if it does, we do a full package parse (which is likely to throw the
1131 // same exception).
1132 // (2) Exception while stating the cache file : If the file doesn't exist, the
1133 // cache is obviously out of date. If the file *does* exist, we can't read it.
1134 // We will attempt to delete and recreate it after parsing the package.
1135 if (ee.errno != OsConstants.ENOENT) {
1136 Slog.w("Error while stating package cache : ", ee);
1137 }
1138
1139 return false;
1140 }
1141 }
1142
1143 /**
1144 * Returns the cached parse result for {@code packageFile} for parse flags {@code flags},
1145 * or {@code null} if no cached result exists.
1146 */
1147 private Package getCachedResult(File packageFile, int flags) {
1148 if (mCacheDir == null) {
1149 return null;
1150 }
1151
1152 final String cacheKey = getCacheKey(packageFile, flags);
1153 final File cacheFile = new File(mCacheDir, cacheKey);
1154
Narayan Kamath988149c2016-12-01 13:32:59 +00001155 try {
Makoto Onuki48e93162017-08-18 11:00:19 -07001156 // If the cache is not up to date, return null.
1157 if (!isCacheUpToDate(packageFile, cacheFile)) {
1158 return null;
1159 }
1160
Narayan Kamath988149c2016-12-01 13:32:59 +00001161 final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001162 Package p = fromCacheEntry(bytes);
1163 if (mCallback != null) {
1164 String[] overlayApks = mCallback.getOverlayApks(p.packageName);
1165 if (overlayApks != null && overlayApks.length > 0) {
1166 for (String overlayApk : overlayApks) {
1167 // If a static RRO is updated, return null.
1168 if (!isCacheUpToDate(new File(overlayApk), cacheFile)) {
1169 return null;
1170 }
1171 }
1172 }
1173 }
1174 return p;
Makoto Onuki48e93162017-08-18 11:00:19 -07001175 } catch (Throwable e) {
Narayan Kamath21a28382017-01-13 10:34:29 +00001176 Slog.w(TAG, "Error reading package cache: ", e);
Narayan Kamath988149c2016-12-01 13:32:59 +00001177
1178 // If something went wrong while reading the cache entry, delete the cache file
1179 // so that we regenerate it the next time.
1180 cacheFile.delete();
1181 return null;
1182 }
1183 }
1184
1185 /**
1186 * Caches the parse result for {@code packageFile} with flags {@code flags}.
1187 */
1188 private void cacheResult(File packageFile, int flags, Package parsed) {
1189 if (mCacheDir == null) {
1190 return;
1191 }
1192
Makoto Onuki48e93162017-08-18 11:00:19 -07001193 try {
1194 final String cacheKey = getCacheKey(packageFile, flags);
1195 final File cacheFile = new File(mCacheDir, cacheKey);
Narayan Kamath988149c2016-12-01 13:32:59 +00001196
Makoto Onuki48e93162017-08-18 11:00:19 -07001197 if (cacheFile.exists()) {
1198 if (!cacheFile.delete()) {
1199 Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
1200 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001201 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001202
Makoto Onuki48e93162017-08-18 11:00:19 -07001203 final byte[] cacheEntry = toCacheEntry(parsed);
Narayan Kamath988149c2016-12-01 13:32:59 +00001204
Makoto Onuki48e93162017-08-18 11:00:19 -07001205 if (cacheEntry == null) {
1206 return;
1207 }
Narayan Kamath988149c2016-12-01 13:32:59 +00001208
Makoto Onuki48e93162017-08-18 11:00:19 -07001209 try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
1210 fos.write(cacheEntry);
1211 } catch (IOException ioe) {
1212 Slog.w(TAG, "Error writing cache entry.", ioe);
1213 cacheFile.delete();
1214 }
1215 } catch (Throwable e) {
1216 Slog.w(TAG, "Error saving package cache.", e);
Jeff Sharkey73767b92014-07-04 20:18:13 -07001217 }
1218 }
1219
1220 /**
1221 * Parse all APKs contained in the given directory, treating them as a
1222 * single package. This also performs sanity checking, such as requiring
1223 * identical package name and version codes, a single base APK, and unique
1224 * split names.
1225 * <p>
1226 * Note that this <em>does not</em> perform signature verification; that
1227 * must be done separately in {@link #collectCertificates(Package, int)}.
1228 */
1229 private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
Adam Lesinski4e862812016-11-21 16:02:24 -08001230 final PackageLite lite = parseClusterPackageLite(packageDir, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001231 if (mOnlyCoreApps && !lite.coreApp) {
1232 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1233 "Not a coreApp: " + packageDir);
1234 }
1235
Adam Lesinski4e862812016-11-21 16:02:24 -08001236 // Build the split dependency tree.
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001237 SparseArray<int[]> splitDependencies = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001238 final SplitAssetLoader assetLoader;
1239 if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) {
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001240 try {
1241 splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite);
1242 assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags);
1243 } catch (SplitAssetDependencyLoader.IllegalDependencyException e) {
1244 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage());
1245 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001246 } else {
1247 assetLoader = new DefaultSplitAssetLoader(lite, flags);
1248 }
1249
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001250 try {
Adam Lesinski4e862812016-11-21 16:02:24 -08001251 final AssetManager assets = assetLoader.getBaseAssetManager();
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001252 final File baseApk = new File(lite.baseCodePath);
1253 final Package pkg = parseBaseApk(baseApk, assets, flags);
1254 if (pkg == null) {
1255 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1256 "Failed to parse base APK: " + baseApk);
1257 }
1258
1259 if (!ArrayUtils.isEmpty(lite.splitNames)) {
1260 final int num = lite.splitNames.length;
1261 pkg.splitNames = lite.splitNames;
1262 pkg.splitCodePaths = lite.splitCodePaths;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001263 pkg.splitRevisionCodes = lite.splitRevisionCodes;
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001264 pkg.splitFlags = new int[num];
Alex Klyubinb9f8a522015-02-03 11:12:59 -08001265 pkg.splitPrivateFlags = new int[num];
Adam Lesinski4e862812016-11-21 16:02:24 -08001266 pkg.applicationInfo.splitNames = pkg.splitNames;
1267 pkg.applicationInfo.splitDependencies = splitDependencies;
Narayan Kamath96c11c52017-08-09 13:07:21 +01001268 pkg.applicationInfo.splitClassLoaderNames = new String[num];
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001269
1270 for (int i = 0; i < num; i++) {
Adam Lesinski4e862812016-11-21 16:02:24 -08001271 final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
1272 parseSplitApk(pkg, i, splitAssets, flags);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001273 }
1274 }
1275
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001276 pkg.setCodePath(packageDir.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001277 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001278 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001279 } catch (IOException e) {
1280 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1281 "Failed to get path: " + lite.baseCodePath, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001282 } finally {
Adam Lesinski4e862812016-11-21 16:02:24 -08001283 IoUtils.closeQuietly(assetLoader);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001285 }
1286
Jeff Sharkey275e0852014-06-17 18:18:49 -07001287 /**
1288 * Parse the given APK file, treating it as as a single monolithic package.
1289 * <p>
1290 * Note that this <em>does not</em> perform signature verification; that
1291 * must be done separately in {@link #collectCertificates(Package, int)}.
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001292 *
1293 * @deprecated external callers should move to
1294 * {@link #parsePackage(File, int)}. Eventually this method will
1295 * be marked private.
Jeff Sharkey275e0852014-06-17 18:18:49 -07001296 */
Jeff Sharkeyd7460572014-07-06 20:44:55 -07001297 @Deprecated
Jeff Sharkey275e0852014-06-17 18:18:49 -07001298 public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
Fyodor Kupolov965fa692016-10-28 18:20:25 -07001299 final AssetManager assets = newConfiguredAssetManager();
Adam Lesinski4e862812016-11-21 16:02:24 -08001300 final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001301 if (mOnlyCoreApps) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001302 if (!lite.coreApp) {
1303 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1304 "Not a coreApp: " + apkFile);
1305 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001306 }
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07001307
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001308 try {
1309 final Package pkg = parseBaseApk(apkFile, assets, flags);
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001310 pkg.setCodePath(apkFile.getCanonicalPath());
Selim Gurun2d291d82016-02-05 17:50:53 -08001311 pkg.setUse32bitAbi(lite.use32bitAbi);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001312 return pkg;
Todd Kennedyddaaf4c2017-11-07 10:01:25 -08001313 } catch (IOException e) {
1314 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1315 "Failed to get path: " + apkFile, e);
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001316 } finally {
1317 IoUtils.closeQuietly(assets);
1318 }
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001319 }
1320
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001321 private static int loadApkIntoAssetManager(AssetManager assets, String apkPath, int flags)
1322 throws PackageParserException {
1323 if ((flags & PARSE_MUST_BE_APK) != 0 && !isApkPath(apkPath)) {
1324 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1325 "Invalid package file: " + apkPath);
1326 }
1327
1328 // The AssetManager guarantees uniqueness for asset paths, so if this asset path
1329 // already exists in the AssetManager, addAssetPath will only return the cookie
1330 // assigned to it.
1331 int cookie = assets.addAssetPath(apkPath);
1332 if (cookie == 0) {
1333 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
1334 "Failed adding asset path: " + apkPath);
1335 }
1336 return cookie;
1337 }
1338
1339 private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
1340 throws PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001341 final String apkPath = apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001342
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07001343 String volumeUuid = null;
1344 if (apkPath.startsWith(MNT_EXPAND)) {
1345 final int end = apkPath.indexOf('/', MNT_EXPAND.length());
1346 volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
1347 }
1348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349 mParseError = PackageManager.INSTALL_SUCCEEDED;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001350 mArchiveSourcePath = apkFile.getAbsolutePath();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001351
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001352 if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001354 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
1355
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08001356 Resources res = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001357 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001359 res = new Resources(assets, mMetrics, null);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001360 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
1361
1362 final String[] outError = new String[1];
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001363 final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001364 if (pkg == null) {
1365 throw new PackageParserException(mParseError,
1366 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001367 }
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001368
Svet Ganov354cd3c2015-12-17 11:35:04 -08001369 pkg.setVolumeUuid(volumeUuid);
1370 pkg.setApplicationVolumeUuid(volumeUuid);
1371 pkg.setBaseCodePath(apkPath);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001372 pkg.setSigningDetails(SigningDetails.UNKNOWN);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001373
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001374 return pkg;
1375
1376 } catch (PackageParserException e) {
1377 throw e;
1378 } catch (Exception e) {
1379 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001380 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001381 } finally {
1382 IoUtils.closeQuietly(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 }
1385
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001386 private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001387 throws PackageParserException {
1388 final String apkPath = pkg.splitCodePaths[splitIndex];
Jeff Sharkey275e0852014-06-17 18:18:49 -07001389
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001390 mParseError = PackageManager.INSTALL_SUCCEEDED;
1391 mArchiveSourcePath = apkPath;
1392
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001393 if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
1394
Adam Lesinski3bcbd902014-08-22 17:01:04 -07001395 final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
1396
Adam Lesinski4e862812016-11-21 16:02:24 -08001397 final Resources res;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001398 XmlResourceParser parser = null;
1399 try {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001400 res = new Resources(assets, mMetrics, null);
Romain Guy408afbf2017-01-25 10:23:03 -08001401 assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001402 Build.VERSION.RESOURCES_SDK_INT);
1403 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
1404
1405 final String[] outError = new String[1];
1406 pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
1407 if (pkg == null) {
1408 throw new PackageParserException(mParseError,
1409 apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
1410 }
1411
1412 } catch (PackageParserException e) {
1413 throw e;
1414 } catch (Exception e) {
1415 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001416 "Failed to read manifest from " + apkPath, e);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001417 } finally {
1418 IoUtils.closeQuietly(parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001419 }
1420 }
1421
1422 /**
1423 * Parse the manifest of a <em>split APK</em>.
1424 * <p>
1425 * Note that split APKs have many more restrictions on what they're capable
1426 * of doing, so many valid features of a base APK have been carefully
1427 * omitted here.
1428 */
1429 private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkey78a13012014-07-15 20:18:34 -07001430 int splitIndex, String[] outError) throws XmlPullParserException, IOException,
1431 PackageParserException {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001432 AttributeSet attrs = parser;
1433
Jeff Sharkey78a13012014-07-15 20:18:34 -07001434 // We parsed manifest tag earlier; just skip past it
Svet Ganov354cd3c2015-12-17 11:35:04 -08001435 parsePackageSplitNames(parser, attrs);
Jeff Sharkey78a13012014-07-15 20:18:34 -07001436
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001437 mParseInstrumentationArgs = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001438
1439 int type;
1440
1441 boolean foundApp = false;
1442
1443 int outerDepth = parser.getDepth();
1444 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1445 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1446 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1447 continue;
1448 }
1449
1450 String tagName = parser.getName();
Adam Lesinski4e862812016-11-21 16:02:24 -08001451 if (tagName.equals(TAG_APPLICATION)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001452 if (foundApp) {
1453 if (RIGID_PARSER) {
1454 outError[0] = "<manifest> has more than one <application>";
1455 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1456 return null;
1457 } else {
1458 Slog.w(TAG, "<manifest> has more than one <application>");
1459 XmlUtils.skipCurrentTag(parser);
1460 continue;
1461 }
1462 }
1463
1464 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001465 if (!parseSplitApplication(pkg, res, parser, flags, splitIndex, outError)) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001466 return null;
1467 }
1468
1469 } else if (RIGID_PARSER) {
1470 outError[0] = "Bad element under <manifest>: "
1471 + parser.getName();
1472 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1473 return null;
1474
1475 } else {
1476 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
1477 + " at " + mArchiveSourcePath + " "
1478 + parser.getPositionDescription());
1479 XmlUtils.skipCurrentTag(parser);
1480 continue;
1481 }
1482 }
1483
1484 if (!foundApp) {
1485 outError[0] = "<manifest> does not contain an <application>";
1486 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
1487 }
1488
1489 return pkg;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001490 }
1491
Patrick Baumann47117fc2017-12-19 10:17:21 -08001492 /** Parses the public keys from the set of signatures. */
1493 public static ArraySet<PublicKey> toSigningKeys(Signature[] signatures)
1494 throws CertificateException {
1495 ArraySet<PublicKey> keys = new ArraySet<>(signatures.length);
1496 for (int i = 0; i < signatures.length; i++) {
1497 keys.add(signatures[i].getPublicKey());
Todd Kennedy66c55532016-02-26 16:22:11 -08001498 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001499 return keys;
Todd Kennedyd9d438a2016-04-06 14:08:14 -07001500 }
1501
1502 /**
Jeff Sharkey275e0852014-06-17 18:18:49 -07001503 * Collect certificates from all the APKs described in the given package,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001504 * populating {@link Package#mSigningDetails}. Also asserts that all APK
Jeff Sharkey275e0852014-06-17 18:18:49 -07001505 * contents are signed correctly and consistently.
1506 */
Todd Kennedy232d29e2017-11-06 14:45:53 -08001507 public static void collectCertificates(Package pkg, @ParseFlags int parseFlags)
Todd Kennedy66c55532016-02-26 16:22:11 -08001508 throws PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001509 collectCertificatesInternal(pkg, parseFlags);
1510 final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
1511 for (int i = 0; i < childCount; i++) {
1512 Package childPkg = pkg.childPackages.get(i);
Patrick Baumann47117fc2017-12-19 10:17:21 -08001513 childPkg.mSigningDetails = pkg.mSigningDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001514 }
1515 }
1516
Todd Kennedy232d29e2017-11-06 14:45:53 -08001517 private static void collectCertificatesInternal(Package pkg, @ParseFlags int parseFlags)
Todd Kennedy66c55532016-02-26 16:22:11 -08001518 throws PackageParserException {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001519 pkg.mSigningDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001520
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001521 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1522 try {
Todd Kennedyf720a9d2016-04-15 09:44:36 -07001523 collectCertificates(pkg, new File(pkg.baseCodePath), parseFlags);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001524
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001525 if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
1526 for (int i = 0; i < pkg.splitCodePaths.length; i++) {
Todd Kennedyf720a9d2016-04-15 09:44:36 -07001527 collectCertificates(pkg, new File(pkg.splitCodePaths[i]), parseFlags);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001528 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07001529 }
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001530 } finally {
1531 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001532 }
1533 }
1534
Todd Kennedy232d29e2017-11-06 14:45:53 -08001535 private static void collectCertificates(Package pkg, File apkFile, @ParseFlags int parseFlags)
Jeff Sharkey275e0852014-06-17 18:18:49 -07001536 throws PackageParserException {
1537 final String apkPath = apkFile.getAbsolutePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538
Patrick Baumann47117fc2017-12-19 10:17:21 -08001539 int minSignatureScheme = SigningDetails.SignatureSchemeVersion.JAR;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001540 if (pkg.applicationInfo.isStaticSharedLibrary()) {
Dan Cashmane92f8422017-12-08 14:02:51 -08001541 // must use v2 signing scheme
Patrick Baumann47117fc2017-12-19 10:17:21 -08001542 minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2;
Dan Cashmane92f8422017-12-08 14:02:51 -08001543 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001544 SigningDetails verified;
Dan Cashman636ea5e2017-12-18 10:38:20 -08001545 if ((parseFlags & PARSE_IS_SYSTEM_DIR) != 0) {
1546 // systemDir APKs are already trusted, save time by not verifying
1547 verified = ApkSignatureVerifier.plsCertsNoVerifyOnlyCerts(
1548 apkPath, minSignatureScheme);
1549 } else {
1550 verified = ApkSignatureVerifier.verify(apkPath, minSignatureScheme);
1551 }
Dan Cashman636ea5e2017-12-18 10:38:20 -08001552
1553 // Verify that entries are signed consistently with the first pkg
1554 // we encountered. Note that for splits, certificates may have
1555 // already been populated during an earlier parse of a base APK.
Patrick Baumann47117fc2017-12-19 10:17:21 -08001556 if (pkg.mSigningDetails == SigningDetails.UNKNOWN) {
1557 pkg.mSigningDetails = verified;
Patrick Baumann9ff55742017-12-14 10:50:18 -08001558 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001559 if (!Signature.areExactMatch(pkg.mSigningDetails.signatures, verified.signatures)) {
Patrick Baumann9ff55742017-12-14 10:50:18 -08001560 throw new PackageParserException(
1561 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
1562 apkPath + " has mismatched certificates");
1563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001564 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565 }
1566
Fyodor Kupolov965fa692016-10-28 18:20:25 -07001567 private static AssetManager newConfiguredAssetManager() {
1568 AssetManager assetManager = new AssetManager();
Romain Guy408afbf2017-01-25 10:23:03 -08001569 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 -07001570 Build.VERSION.RESOURCES_SDK_INT);
1571 return assetManager;
1572 }
1573
Jeff Sharkey275e0852014-06-17 18:18:49 -07001574 /**
1575 * Utility method that retrieves lightweight details about a single APK
1576 * file, including package name, split name, and install location.
1577 *
1578 * @param apkFile path to a single APK
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001579 * @param flags optional parse flags, such as
1580 * {@link #PARSE_COLLECT_CERTIFICATES}
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001581 */
Jeff Sharkey275e0852014-06-17 18:18:49 -07001582 public static ApkLite parseApkLite(File apkFile, int flags)
1583 throws PackageParserException {
Dianne Hackbornca3872c2017-10-30 14:19:32 -07001584 return parseApkLiteInner(apkFile, null, null, flags);
1585 }
1586
1587 /**
1588 * Utility method that retrieves lightweight details about a single APK
1589 * file, including package name, split name, and install location.
1590 *
1591 * @param fd already open file descriptor of an apk file
1592 * @param debugPathName arbitrary text name for this file, for debug output
1593 * @param flags optional parse flags, such as
1594 * {@link #PARSE_COLLECT_CERTIFICATES}
1595 */
1596 public static ApkLite parseApkLite(FileDescriptor fd, String debugPathName, int flags)
1597 throws PackageParserException {
1598 return parseApkLiteInner(null, fd, debugPathName, flags);
1599 }
1600
1601 private static ApkLite parseApkLiteInner(File apkFile, FileDescriptor fd, String debugPathName,
1602 int flags) throws PackageParserException {
1603 final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001604
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001605 AssetManager assets = null;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001606 XmlResourceParser parser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001607 try {
Adam Lesinski4e862812016-11-21 16:02:24 -08001608 assets = newConfiguredAssetManager();
Dianne Hackbornca3872c2017-10-30 14:19:32 -07001609 int cookie = fd != null
1610 ? assets.addAssetFd(fd, debugPathName) : assets.addAssetPath(apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001611 if (cookie == 0) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001612 throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
1613 "Failed to parse " + apkPath);
Kenny Root1ebd74a2011-08-03 15:09:44 -07001614 }
1615
Kenny Root05ca4c92011-09-15 10:36:25 -07001616 final DisplayMetrics metrics = new DisplayMetrics();
1617 metrics.setToDefaults();
Jeff Sharkey275e0852014-06-17 18:18:49 -07001618
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001619 parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
Kenny Root05ca4c92011-09-15 10:36:25 -07001620
Patrick Baumann47117fc2017-12-19 10:17:21 -08001621 final SigningDetails signingDetails;
Jeff Sharkeybb7b7be2014-08-19 16:18:28 -07001622 if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
1623 // TODO: factor signature related items out of Package object
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00001624 final Package tempPkg = new Package((String) null);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001625 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
1626 try {
Alex Klyubinabbc2bad2017-01-04 11:28:47 -08001627 collectCertificates(tempPkg, apkFile, flags);
Todd Kennedy0f4bc2b2016-04-06 07:46:13 -07001628 } finally {
1629 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1630 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08001631 signingDetails = tempPkg.mSigningDetails;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001632 } else {
Patrick Baumann47117fc2017-12-19 10:17:21 -08001633 signingDetails = SigningDetails.UNKNOWN;
Jeff Sharkey275e0852014-06-17 18:18:49 -07001634 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001635
Jeff Sharkey275e0852014-06-17 18:18:49 -07001636 final AttributeSet attrs = parser;
Patrick Baumann47117fc2017-12-19 10:17:21 -08001637 return parseApkLite(apkPath, parser, attrs, signingDetails);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001638
1639 } catch (XmlPullParserException | IOException | RuntimeException e) {
Dianne Hackborn34041732017-01-31 15:27:13 -08001640 Slog.w(TAG, "Failed to parse " + apkPath, e);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001641 throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
1642 "Failed to parse " + apkPath, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 } finally {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001644 IoUtils.closeQuietly(parser);
Adam Lesinski4e862812016-11-21 16:02:24 -08001645 IoUtils.closeQuietly(assets);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 }
1648
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001649 private static String validateName(String name, boolean requireSeparator,
1650 boolean requireFilename) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001651 final int N = name.length();
1652 boolean hasSep = false;
1653 boolean front = true;
1654 for (int i=0; i<N; i++) {
1655 final char c = name.charAt(i);
1656 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
1657 front = false;
1658 continue;
1659 }
1660 if (!front) {
1661 if ((c >= '0' && c <= '9') || c == '_') {
1662 continue;
1663 }
1664 }
1665 if (c == '.') {
1666 hasSep = true;
1667 front = true;
1668 continue;
1669 }
1670 return "bad character '" + c + "'";
1671 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001672 if (requireFilename && !FileUtils.isValidExtFilename(name)) {
1673 return "Invalid filename";
1674 }
1675 return hasSep || !requireSeparator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 ? null : "must have at least one '.' separator";
1677 }
1678
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001679 private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
Svet Ganov354cd3c2015-12-17 11:35:04 -08001680 AttributeSet attrs) throws IOException, XmlPullParserException,
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001681 PackageParserException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682
1683 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07001684 while ((type = parser.next()) != XmlPullParser.START_TAG
1685 && type != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001686 }
1687
Kenny Rootd2d29252011-08-08 11:27:57 -07001688 if (type != XmlPullParser.START_TAG) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001689 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1690 "No start tag found");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001691 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001692 if (!parser.getName().equals(TAG_MANIFEST)) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001693 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1694 "No <manifest> tag");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001695 }
1696
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001697 final String packageName = attrs.getAttributeValue(null, "package");
1698 if (!"android".equals(packageName)) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001699 final String error = validateName(packageName, true, true);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001700 if (error != null) {
1701 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1702 "Invalid manifest package: " + error);
1703 }
1704 }
1705
Jeff Sharkey275e0852014-06-17 18:18:49 -07001706 String splitName = attrs.getAttributeValue(null, "split");
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001707 if (splitName != null) {
Jeff Sharkey275e0852014-06-17 18:18:49 -07001708 if (splitName.length() == 0) {
1709 splitName = null;
1710 } else {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07001711 final String error = validateName(splitName, false, false);
Jeff Sharkey275e0852014-06-17 18:18:49 -07001712 if (error != null) {
1713 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
1714 "Invalid manifest split: " + error);
1715 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001716 }
1717 }
1718
1719 return Pair.create(packageName.intern(),
1720 (splitName != null) ? splitName.intern() : splitName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001721 }
1722
Adam Lesinski4e862812016-11-21 16:02:24 -08001723 private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001724 SigningDetails signingDetails)
Adam Lesinski4e862812016-11-21 16:02:24 -08001725 throws IOException, XmlPullParserException, PackageParserException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001726 final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001727
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001728 int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001729 int versionCode = 0;
Dianne Hackborn3accca02013-09-20 09:32:11 -07001730 int versionCodeMajor = 0;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001731 int revisionCode = 0;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001732 boolean coreApp = false;
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001733 boolean debuggable = false;
Narayan Kamathff110bd2014-07-04 18:30:45 +01001734 boolean multiArch = false;
Selim Gurun2d291d82016-02-05 17:50:53 -08001735 boolean use32bitAbi = false;
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001736 boolean extractNativeLibs = true;
Adam Lesinski4e862812016-11-21 16:02:24 -08001737 boolean isolatedSplits = false;
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001738 boolean isFeatureSplit = false;
1739 String configForSplit = null;
Adam Lesinski4e862812016-11-21 16:02:24 -08001740 String usesSplitName = null;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001741
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001742 for (int i = 0; i < attrs.getAttributeCount(); i++) {
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001743 final String attr = attrs.getAttributeName(i);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001744 if (attr.equals("installLocation")) {
1745 installLocation = attrs.getAttributeIntValue(i,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07001746 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001747 } else if (attr.equals("versionCode")) {
1748 versionCode = attrs.getAttributeIntValue(i, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001749 } else if (attr.equals("versionCodeMajor")) {
1750 versionCodeMajor = attrs.getAttributeIntValue(i, 0);
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001751 } else if (attr.equals("revisionCode")) {
1752 revisionCode = attrs.getAttributeIntValue(i, 0);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001753 } else if (attr.equals("coreApp")) {
1754 coreApp = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski4e862812016-11-21 16:02:24 -08001755 } else if (attr.equals("isolatedSplits")) {
1756 isolatedSplits = attrs.getAttributeBooleanValue(i, false);
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001757 } else if (attr.equals("configForSplit")) {
1758 configForSplit = attrs.getAttributeValue(i);
1759 } else if (attr.equals("isFeatureSplit")) {
1760 isFeatureSplit = attrs.getAttributeBooleanValue(i, false);
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08001761 }
1762 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001763
1764 // Only search the tree when the tag is directly below <manifest>
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001765 int type;
Kenny Root05ca4c92011-09-15 10:36:25 -07001766 final int searchDepth = parser.getDepth() + 1;
1767
1768 final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
1769 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1770 && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
1771 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1772 continue;
1773 }
1774
Adam Lesinski4e862812016-11-21 16:02:24 -08001775 if (parser.getDepth() != searchDepth) {
1776 continue;
1777 }
1778
1779 if (TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
1780 final VerifierInfo verifier = parseVerifier(attrs);
Kenny Root05ca4c92011-09-15 10:36:25 -07001781 if (verifier != null) {
1782 verifiers.add(verifier);
1783 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001784 } else if (TAG_APPLICATION.equals(parser.getName())) {
Narayan Kamatha8755a82014-07-15 12:26:35 +01001785 for (int i = 0; i < attrs.getAttributeCount(); ++i) {
1786 final String attr = attrs.getAttributeName(i);
Tamas Berghammerd6dd6b82016-10-07 19:12:51 +01001787 if ("debuggable".equals(attr)) {
1788 debuggable = attrs.getAttributeBooleanValue(i, false);
1789 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001790 if ("multiArch".equals(attr)) {
1791 multiArch = attrs.getAttributeBooleanValue(i, false);
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001792 }
Selim Gurun2d291d82016-02-05 17:50:53 -08001793 if ("use32bitAbi".equals(attr)) {
1794 use32bitAbi = attrs.getAttributeBooleanValue(i, false);
Tao Baic9a02372016-01-12 15:02:24 -08001795 }
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07001796 if ("extractNativeLibs".equals(attr)) {
1797 extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
Narayan Kamatha8755a82014-07-15 12:26:35 +01001798 }
1799 }
Adam Lesinski4e862812016-11-21 16:02:24 -08001800 } else if (TAG_USES_SPLIT.equals(parser.getName())) {
1801 if (usesSplitName != null) {
1802 Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
1803 continue;
1804 }
1805
1806 usesSplitName = attrs.getAttributeValue(ANDROID_RESOURCES, "name");
1807 if (usesSplitName == null) {
1808 throw new PackageParserException(
1809 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
1810 "<uses-split> tag requires 'android:name' attribute");
1811 }
Narayan Kamatha8755a82014-07-15 12:26:35 +01001812 }
Kenny Root05ca4c92011-09-15 10:36:25 -07001813 }
1814
Adam Lesinski1665d0f2017-03-10 14:46:57 -08001815 return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
Dianne Hackborn3accca02013-09-20 09:32:11 -07001816 configForSplit, usesSplitName, versionCode, versionCodeMajor, revisionCode,
Patrick Baumann47117fc2017-12-19 10:17:21 -08001817 installLocation, verifiers, signingDetails, coreApp, debuggable,
Dianne Hackborn3accca02013-09-20 09:32:11 -07001818 multiArch, use32bitAbi, extractNativeLibs, isolatedSplits);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001819 }
1820
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001821 /**
Svet Ganov354cd3c2015-12-17 11:35:04 -08001822 * Parses a child package and adds it to the parent if successful. If you add
1823 * new tags that need to be supported by child packages make sure to add them
1824 * to {@link #CHILD_PACKAGE_TAGS}.
1825 *
1826 * @param parentPkg The parent that contains the child
1827 * @param res Resources against which to resolve values
1828 * @param parser Parser of the manifest
1829 * @param flags Flags about how to parse
1830 * @param outError Human readable error if parsing fails
1831 * @return True of parsing succeeded.
1832 *
1833 * @throws XmlPullParserException
1834 * @throws IOException
1835 */
1836 private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser,
1837 int flags, String[] outError) throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001838 // Make sure we have a valid child package name
1839 String childPackageName = parser.getAttributeValue(null, "package");
1840 if (validateName(childPackageName, true, false) != null) {
1841 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1842 return false;
1843 }
1844
1845 // Child packages must be unique
1846 if (childPackageName.equals(parentPkg.packageName)) {
1847 String message = "Child package name cannot be equal to parent package name: "
1848 + parentPkg.packageName;
1849 Slog.w(TAG, message);
1850 outError[0] = message;
1851 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1852 return false;
1853 }
1854
1855 // Child packages must be unique
1856 if (parentPkg.hasChildPackage(childPackageName)) {
1857 String message = "Duplicate child package:" + childPackageName;
1858 Slog.w(TAG, message);
1859 outError[0] = message;
1860 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
1861 return false;
1862 }
1863
1864 // Go ahead and parse the child
1865 Package childPkg = new Package(childPackageName);
1866
1867 // Child package inherits parent version code/name/target SDK
1868 childPkg.mVersionCode = parentPkg.mVersionCode;
1869 childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
1870 childPkg.mVersionName = parentPkg.mVersionName;
1871 childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
Todd Kennedy89d60182016-03-11 11:18:32 -08001872 childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001873
1874 childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
1875 if (childPkg == null) {
1876 // If we got null then error was set during child parsing
1877 return false;
1878 }
1879
1880 // Set the parent-child relation
1881 if (parentPkg.childPackages == null) {
1882 parentPkg.childPackages = new ArrayList<>();
1883 }
1884 parentPkg.childPackages.add(childPkg);
1885 childPkg.parentPackage = parentPkg;
1886
1887 return true;
1888 }
1889
1890 /**
1891 * Parse the manifest of a <em>base APK</em>. When adding new features you
1892 * need to consider whether they should be supported by split APKs and child
1893 * packages.
1894 *
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001895 * @param apkPath The package apk file path
Svet Ganov354cd3c2015-12-17 11:35:04 -08001896 * @param res The resources from which to resolve values
1897 * @param parser The manifest parser
1898 * @param flags Flags how to parse
1899 * @param outError Human readable error message
1900 * @return Parsed package or null on error.
1901 *
1902 * @throws XmlPullParserException
1903 * @throws IOException
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001904 */
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001905 private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07001906 String[] outError) throws XmlPullParserException, IOException {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001907 final String splitName;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001908 final String pkgName;
1909
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001910 try {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001911 Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001912 pkgName = packageSplit.first;
1913 splitName = packageSplit.second;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001914
1915 if (!TextUtils.isEmpty(splitName)) {
1916 outError[0] = "Expected base APK, but found split " + splitName;
1917 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1918 return null;
1919 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001920 } catch (PackageParserException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001921 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
1922 return null;
1923 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001924
Jaekyun Seok30dc2a02017-04-11 09:41:11 +09001925 if (mCallback != null) {
1926 String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath);
1927 if (overlayPaths != null && overlayPaths.length > 0) {
1928 for (String overlayPath : overlayPaths) {
1929 res.getAssets().addOverlayPath(overlayPath);
1930 }
1931 }
1932 }
1933
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07001934 final Package pkg = new Package(pkgName);
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001935
Svet Ganov354cd3c2015-12-17 11:35:04 -08001936 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937 com.android.internal.R.styleable.AndroidManifest);
Svet Ganov354cd3c2015-12-17 11:35:04 -08001938
Dianne Hackborn3accca02013-09-20 09:32:11 -07001939 pkg.mVersionCode = sa.getInteger(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001940 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001941 pkg.mVersionCodeMajor = sa.getInteger(
1942 com.android.internal.R.styleable.AndroidManifest_versionCodeMajor, 0);
1943 pkg.applicationInfo.versionCode = pkg.getLongVersionCode();
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08001944 pkg.baseRevisionCode = sa.getInteger(
1945 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001946 pkg.mVersionName = sa.getNonConfigurationString(
1947 com.android.internal.R.styleable.AndroidManifest_versionName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001948 if (pkg.mVersionName != null) {
1949 pkg.mVersionName = pkg.mVersionName.intern();
1950 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08001951
1952 pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
1953
Alan Viveretteb6a25732017-11-21 14:49:24 -05001954 pkg.mCompileSdkVersion = sa.getInteger(
1955 com.android.internal.R.styleable.AndroidManifest_compileSdkVersion, 0);
1956 pkg.applicationInfo.compileSdkVersion = pkg.mCompileSdkVersion;
1957 pkg.mCompileSdkVersionCodename = sa.getNonConfigurationString(
1958 com.android.internal.R.styleable.AndroidManifest_compileSdkVersionCodename, 0);
1959 if (pkg.mCompileSdkVersionCodename != null) {
1960 pkg.mCompileSdkVersionCodename = pkg.mCompileSdkVersionCodename.intern();
1961 }
1962 pkg.applicationInfo.compileSdkVersionCodename = pkg.mCompileSdkVersionCodename;
1963
Svet Ganov354cd3c2015-12-17 11:35:04 -08001964 sa.recycle();
1965
1966 return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
1967 }
1968
1969 /**
1970 * This is the common parsing routing for handling parent and child
1971 * packages in a base APK. The difference between parent and child
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001972 * parsing is that some tags are not supported by child packages as
Svet Ganov354cd3c2015-12-17 11:35:04 -08001973 * well as some manifest attributes are ignored. The implementation
Todd Kennedyfdd241a2016-04-28 12:26:53 -07001974 * assumes the calling code has already handled the manifest tag if needed
Svet Ganov354cd3c2015-12-17 11:35:04 -08001975 * (this applies to the parent only).
1976 *
1977 * @param pkg The package which to populate
1978 * @param acceptedTags Which tags to handle, null to handle all
1979 * @param res Resources against which to resolve values
1980 * @param parser Parser of the manifest
1981 * @param flags Flags about how to parse
1982 * @param outError Human readable error if parsing fails
1983 * @return The package if parsing succeeded or null.
1984 *
1985 * @throws XmlPullParserException
1986 * @throws IOException
1987 */
1988 private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
1989 XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
1990 IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08001991 mParseInstrumentationArgs = null;
Svet Ganov354cd3c2015-12-17 11:35:04 -08001992
1993 int type;
1994 boolean foundApp = false;
1995
1996 TypedArray sa = res.obtainAttributes(parser,
1997 com.android.internal.R.styleable.AndroidManifest);
1998
Dianne Hackborncf244ad2010-03-09 15:00:30 -08001999 String str = sa.getNonConfigurationString(
2000 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
2001 if (str != null && str.length() > 0) {
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002002 String nameError = validateName(str, true, false);
Svet Ganov354cd3c2015-12-17 11:35:04 -08002003 if (nameError != null && !"android".equals(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002004 outError[0] = "<manifest> specifies bad sharedUserId name \""
2005 + str + "\": " + nameError;
2006 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
2007 return null;
2008 }
2009 pkg.mSharedUserId = str.intern();
2010 pkg.mSharedUserLabel = sa.getResourceId(
2011 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
2012 }
Suchi Amalapurapuaaec7792010-02-25 11:49:43 -08002013
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08002014 pkg.installLocation = sa.getInteger(
2015 com.android.internal.R.styleable.AndroidManifest_installLocation,
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07002016 PARSE_DEFAULT_INSTALL_LOCATION);
Dianne Hackborn54e570f2010-10-04 18:32:32 -07002017 pkg.applicationInfo.installLocation = pkg.installLocation;
Kenny Root7cb9be22012-05-30 15:30:37 -07002018
Todd Kennedy11e45072017-01-25 13:24:21 -08002019 final int targetSandboxVersion = sa.getInteger(
2020 com.android.internal.R.styleable.AndroidManifest_targetSandboxVersion,
2021 PARSE_DEFAULT_TARGET_SANDBOX);
2022 pkg.applicationInfo.targetSandboxVersion = targetSandboxVersion;
Alan Viverettefd274a02014-03-27 15:39:15 -07002023
Kenny Root7cb9be22012-05-30 15:30:37 -07002024 /* Set the global "forward lock" flag */
2025 if ((flags & PARSE_FORWARD_LOCK) != 0) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08002026 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
Kenny Root7cb9be22012-05-30 15:30:37 -07002027 }
2028
2029 /* Set the global "on SD card" flag */
Jeff Sharkeyb2b9ab82015-04-05 21:10:42 -07002030 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
Kenny Root7cb9be22012-05-30 15:30:37 -07002031 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
2032 }
2033
Adam Lesinski4e862812016-11-21 16:02:24 -08002034 if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) {
2035 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
2036 }
2037
Dianne Hackborn723738c2009-06-25 19:48:04 -07002038 // Resource boolean are -1, so 1 means we don't know the value.
2039 int supportsSmallScreens = 1;
2040 int supportsNormalScreens = 1;
2041 int supportsLargeScreens = 1;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002042 int supportsXLargeScreens = 1;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002043 int resizeable = 1;
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002044 int anyDensity = 1;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002045
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046 int outerDepth = parser.getDepth();
Kenny Rootd2d29252011-08-08 11:27:57 -07002047 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2048 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2049 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002050 continue;
2051 }
2052
2053 String tagName = parser.getName();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002054
2055 if (acceptedTags != null && !acceptedTags.contains(tagName)) {
2056 Slog.w(TAG, "Skipping unsupported element under <manifest>: "
2057 + tagName + " at " + mArchiveSourcePath + " "
2058 + parser.getPositionDescription());
2059 XmlUtils.skipCurrentTag(parser);
2060 continue;
2061 }
2062
2063 if (tagName.equals(TAG_APPLICATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002064 if (foundApp) {
2065 if (RIGID_PARSER) {
2066 outError[0] = "<manifest> has more than one <application>";
2067 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2068 return null;
2069 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002070 Slog.w(TAG, "<manifest> has more than one <application>");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002071 XmlUtils.skipCurrentTag(parser);
2072 continue;
2073 }
2074 }
2075
2076 foundApp = true;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002077 if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002078 return null;
2079 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002080 } else if (tagName.equals(TAG_OVERLAY)) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002081 sa = res.obtainAttributes(parser,
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002082 com.android.internal.R.styleable.AndroidManifestResourceOverlay);
2083 pkg.mOverlayTarget = sa.getString(
2084 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002085 pkg.mOverlayPriority = sa.getInt(
2086 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
2087 0);
Jaekyun Seok04342892017-03-02 15:24:19 +09002088 pkg.mIsStaticOverlay = sa.getBoolean(
2089 com.android.internal.R.styleable.AndroidManifestResourceOverlay_isStatic,
2090 false);
Todd Leeea2f3be2017-03-16 14:00:52 -07002091 final String propName = sa.getString(
2092 com.android.internal.R.styleable
2093 .AndroidManifestResourceOverlay_requiredSystemPropertyName);
2094 final String propValue = sa.getString(
2095 com.android.internal.R.styleable
2096 .AndroidManifestResourceOverlay_requiredSystemPropertyValue);
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002097 sa.recycle();
2098
2099 if (pkg.mOverlayTarget == null) {
2100 outError[0] = "<overlay> does not specify a target package";
2101 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2102 return null;
2103 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002104
Jaekyun Seok42d53f62017-04-10 13:48:58 +09002105 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
2106 outError[0] = "<overlay> priority must be between 0 and 9999";
2107 mParseError =
2108 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2109 return null;
2110 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002111
2112 // check to see if overlay should be excluded based on system property condition
2113 if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
2114 Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and "
2115 + pkg.baseCodePath+ ": overlay ignored due to required system property: "
2116 + propName + " with value: " + propValue);
2117 return null;
Jaekyun Seok04342892017-03-02 15:24:19 +09002118 }
Todd Leeea2f3be2017-03-16 14:00:52 -07002119
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01002120 XmlUtils.skipCurrentTag(parser);
2121
Svet Ganov354cd3c2015-12-17 11:35:04 -08002122 } else if (tagName.equals(TAG_KEY_SETS)) {
2123 if (!parseKeySets(pkg, res, parser, outError)) {
Geremy Condraf1bcca82013-01-07 22:35:24 -08002124 return null;
2125 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002126 } else if (tagName.equals(TAG_PERMISSION_GROUP)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002127 if (!parsePermissionGroup(pkg, flags, 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_PERMISSION)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002131 if (!parsePermission(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132 return null;
2133 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002134 } else if (tagName.equals(TAG_PERMISSION_TREE)) {
Dianne Hackborncd154e92017-02-28 17:37:35 -08002135 if (!parsePermissionTree(pkg, res, parser, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002136 return null;
2137 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002138 } else if (tagName.equals(TAG_USES_PERMISSION)) {
2139 if (!parseUsesPermission(pkg, res, parser)) {
Svetoslav96a77162015-04-03 13:58:33 -07002140 return null;
2141 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002142 } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
2143 || tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
2144 if (!parseUsesPermission(pkg, res, parser)) {
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002145 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002147 } else if (tagName.equals(TAG_USES_CONFIGURATION)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002148 ConfigurationInfo cPref = new ConfigurationInfo();
Svet Ganov354cd3c2015-12-17 11:35:04 -08002149 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002150 com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
2151 cPref.reqTouchScreen = sa.getInt(
2152 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
2153 Configuration.TOUCHSCREEN_UNDEFINED);
2154 cPref.reqKeyboardType = sa.getInt(
2155 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
2156 Configuration.KEYBOARD_UNDEFINED);
2157 if (sa.getBoolean(
2158 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
2159 false)) {
2160 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
2161 }
2162 cPref.reqNavigation = sa.getInt(
2163 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
2164 Configuration.NAVIGATION_UNDEFINED);
2165 if (sa.getBoolean(
2166 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
2167 false)) {
2168 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
2169 }
2170 sa.recycle();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002171 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172
2173 XmlUtils.skipCurrentTag(parser);
2174
Svet Ganov354cd3c2015-12-17 11:35:04 -08002175 } else if (tagName.equals(TAG_USES_FEATURE)) {
2176 FeatureInfo fi = parseUsesFeature(res, parser);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002177 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
2178
Dianne Hackborn49237342009-08-27 20:08:01 -07002179 if (fi.name == null) {
2180 ConfigurationInfo cPref = new ConfigurationInfo();
2181 cPref.reqGlEsVersion = fi.reqGlEsVersion;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07002182 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
Dianne Hackborn49237342009-08-27 20:08:01 -07002183 }
Suchi Amalapurapud299b812009-06-05 10:26:19 -07002184
2185 XmlUtils.skipCurrentTag(parser);
2186
Svet Ganov354cd3c2015-12-17 11:35:04 -08002187 } else if (tagName.equals(TAG_FEATURE_GROUP)) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002188 FeatureGroupInfo group = new FeatureGroupInfo();
2189 ArrayList<FeatureInfo> features = null;
2190 final int innerDepth = parser.getDepth();
2191 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2192 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
2193 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2194 continue;
2195 }
Adam Lesinski2c72b682014-06-24 09:56:01 -07002196
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002197 final String innerTagName = parser.getName();
2198 if (innerTagName.equals("uses-feature")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002199 FeatureInfo featureInfo = parseUsesFeature(res, parser);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002200 // FeatureGroups are stricter and mandate that
2201 // any <uses-feature> declared are mandatory.
2202 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
2203 features = ArrayUtils.add(features, featureInfo);
2204 } else {
2205 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
2206 " at " + mArchiveSourcePath + " " +
2207 parser.getPositionDescription());
2208 }
2209 XmlUtils.skipCurrentTag(parser);
2210 }
2211
2212 if (features != null) {
2213 group.features = new FeatureInfo[features.size()];
2214 group.features = features.toArray(group.features);
2215 }
2216 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
Adam Lesinski2c72b682014-06-24 09:56:01 -07002217
Svet Ganov354cd3c2015-12-17 11:35:04 -08002218 } else if (tagName.equals(TAG_USES_SDK)) {
Suchi Amalapurapu8d5ae982009-10-06 09:26:09 -07002219 if (SDK_VERSION > 0) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08002220 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002221 com.android.internal.R.styleable.AndroidManifestUsesSdk);
2222
Todd Kennedy4f657082016-06-28 10:31:05 -07002223 int minVers = 1;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002224 String minCode = null;
2225 int targetVers = 0;
2226 String targetCode = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002227
Dianne Hackborn851a5412009-05-08 12:06:44 -07002228 TypedValue val = sa.peekValue(
2229 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
2230 if (val != null) {
2231 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
2232 targetCode = minCode = val.string.toString();
2233 } else {
2234 // If it's not a string, it's an integer.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002235 targetVers = minVers = val.data;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002236 }
2237 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002238
Dianne Hackborn851a5412009-05-08 12:06:44 -07002239 val = sa.peekValue(
2240 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
2241 if (val != null) {
2242 if (val.type == TypedValue.TYPE_STRING && val.string != null) {
Todd Kennedy89d60182016-03-11 11:18:32 -08002243 targetCode = val.string.toString();
2244 if (minCode == null) {
2245 minCode = targetCode;
2246 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002247 } else {
2248 // If it's not a string, it's an integer.
2249 targetVers = val.data;
2250 }
2251 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002253 sa.recycle();
2254
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002255 final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers, minCode,
2256 SDK_VERSION, SDK_CODENAMES, outError);
2257 if (minSdkVersion < 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002258 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2259 return null;
2260 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002261
Patrick Baumannccb20b82018-01-08 13:22:46 -08002262 boolean defaultToCurrentDevBranch = (flags & PARSE_FORCE_SDK) != 0;
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002263 final int targetSdkVersion = PackageParser.computeTargetSdkVersion(targetVers,
Patrick Baumannccb20b82018-01-08 13:22:46 -08002264 targetCode, SDK_CODENAMES, outError, defaultToCurrentDevBranch);
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002265 if (targetSdkVersion < 0) {
2266 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
2267 return null;
Dianne Hackborn851a5412009-05-08 12:06:44 -07002268 }
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002269
2270 pkg.applicationInfo.minSdkVersion = minSdkVersion;
2271 pkg.applicationInfo.targetSdkVersion = targetSdkVersion;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272 }
2273
2274 XmlUtils.skipCurrentTag(parser);
2275
Svet Ganov354cd3c2015-12-17 11:35:04 -08002276 } else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
2277 sa = res.obtainAttributes(parser,
Dianne Hackborn723738c2009-06-25 19:48:04 -07002278 com.android.internal.R.styleable.AndroidManifestSupportsScreens);
2279
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002280 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
2281 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
2282 0);
2283 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
2284 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
2285 0);
Dianne Hackborn2762ff32011-06-01 21:27:05 -07002286 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
2287 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
2288 0);
Dianne Hackborndf6e9802011-05-26 14:20:23 -07002289
Dianne Hackborn723738c2009-06-25 19:48:04 -07002290 // This is a trick to get a boolean and still able to detect
2291 // if a value was actually set.
2292 supportsSmallScreens = sa.getInteger(
2293 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
2294 supportsSmallScreens);
2295 supportsNormalScreens = sa.getInteger(
2296 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
2297 supportsNormalScreens);
2298 supportsLargeScreens = sa.getInteger(
2299 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
2300 supportsLargeScreens);
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002301 supportsXLargeScreens = sa.getInteger(
2302 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
2303 supportsXLargeScreens);
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002304 resizeable = sa.getInteger(
2305 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002306 resizeable);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002307 anyDensity = sa.getInteger(
2308 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
2309 anyDensity);
Dianne Hackborn723738c2009-06-25 19:48:04 -07002310
2311 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002312
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07002313 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002314
Svet Ganov354cd3c2015-12-17 11:35:04 -08002315 } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
2316 sa = res.obtainAttributes(parser,
Dianne Hackborn854060af2009-07-09 18:14:31 -07002317 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
2318
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002319 // Note: don't allow this value to be a reference to a resource
2320 // that may change.
Dianne Hackborn854060af2009-07-09 18:14:31 -07002321 String name = sa.getNonResourceString(
2322 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
2323
2324 sa.recycle();
2325
Todd Kennedy232d29e2017-11-06 14:45:53 -08002326 if (name != null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002327 if (pkg.protectedBroadcasts == null) {
2328 pkg.protectedBroadcasts = new ArrayList<String>();
2329 }
2330 if (!pkg.protectedBroadcasts.contains(name)) {
2331 pkg.protectedBroadcasts.add(name.intern());
2332 }
2333 }
2334
2335 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002336
Svet Ganov354cd3c2015-12-17 11:35:04 -08002337 } else if (tagName.equals(TAG_INSTRUMENTATION)) {
2338 if (parseInstrumentation(pkg, res, parser, outError) == null) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002339 return null;
2340 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002341 } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
2342 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002343 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2344
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002345 String orig =sa.getNonConfigurationString(
2346 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002347 if (!pkg.packageName.equals(orig)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002348 if (pkg.mOriginalPackages == null) {
2349 pkg.mOriginalPackages = new ArrayList<String>();
2350 pkg.mRealPackage = pkg.packageName;
2351 }
2352 pkg.mOriginalPackages.add(orig);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002353 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002354
2355 sa.recycle();
2356
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002357 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002358
Svet Ganov354cd3c2015-12-17 11:35:04 -08002359 } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
2360 sa = res.obtainAttributes(parser,
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002361 com.android.internal.R.styleable.AndroidManifestOriginalPackage);
2362
Dianne Hackborncf244ad2010-03-09 15:00:30 -08002363 String name = sa.getNonConfigurationString(
2364 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002365
2366 sa.recycle();
2367
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002368 if (name != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002369 if (pkg.mAdoptPermissions == null) {
2370 pkg.mAdoptPermissions = new ArrayList<String>();
2371 }
2372 pkg.mAdoptPermissions.add(name);
2373 }
2374
2375 XmlUtils.skipCurrentTag(parser);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002376
Svet Ganov354cd3c2015-12-17 11:35:04 -08002377 } else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002378 // Just skip this tag
2379 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_COMPATIBLE_SCREENS)) {
Dianne Hackborna0b46c92010-10-21 15:32:06 -07002383 // Just skip this tag
2384 XmlUtils.skipCurrentTag(parser);
2385 continue;
Svet Ganov354cd3c2015-12-17 11:35:04 -08002386 } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
Michael Wrighteaeb1902013-09-05 18:15:57 -07002387 XmlUtils.skipCurrentTag(parser);
2388 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002389
Svet Ganov354cd3c2015-12-17 11:35:04 -08002390 } else if (tagName.equals(TAG_EAT_COMMENT)) {
Dianne Hackborn854060af2009-07-09 18:14:31 -07002391 // Just skip this tag
2392 XmlUtils.skipCurrentTag(parser);
2393 continue;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002394
Svet Ganov354cd3c2015-12-17 11:35:04 -08002395 } else if (tagName.equals(TAG_PACKAGE)) {
Svet Ganova7532cf2016-05-02 08:13:17 -07002396 if (!MULTI_PACKAGE_APK_ENABLED) {
2397 XmlUtils.skipCurrentTag(parser);
2398 continue;
2399 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002400 if (!parseBaseApkChild(pkg, res, parser, flags, outError)) {
2401 // If parsing a child failed the error is already set
2402 return null;
2403 }
Todd Kennedyfdd241a2016-04-28 12:26:53 -07002404
2405 } else if (tagName.equals(TAG_RESTRICT_UPDATE)) {
2406 if ((flags & PARSE_IS_SYSTEM_DIR) != 0) {
2407 sa = res.obtainAttributes(parser,
2408 com.android.internal.R.styleable.AndroidManifestRestrictUpdate);
2409 final String hash = sa.getNonConfigurationString(
2410 com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0);
2411 sa.recycle();
2412
2413 pkg.restrictUpdateHash = null;
2414 if (hash != null) {
2415 final int hashLength = hash.length();
2416 final byte[] hashBytes = new byte[hashLength / 2];
2417 for (int i = 0; i < hashLength; i += 2){
2418 hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4)
2419 + Character.digit(hash.charAt(i + 1), 16));
2420 }
2421 pkg.restrictUpdateHash = hashBytes;
2422 }
2423 }
2424
2425 XmlUtils.skipCurrentTag(parser);
2426
Dianne Hackborn854060af2009-07-09 18:14:31 -07002427 } else if (RIGID_PARSER) {
2428 outError[0] = "Bad element under <manifest>: "
2429 + parser.getName();
2430 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2431 return null;
2432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002433 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07002434 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07002435 + " at " + mArchiveSourcePath + " "
2436 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002437 XmlUtils.skipCurrentTag(parser);
2438 continue;
2439 }
2440 }
2441
2442 if (!foundApp && pkg.instrumentation.size() == 0) {
2443 outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
2444 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
2445 }
2446
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002447 final int NP = PackageParser.NEW_PERMISSIONS.length;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002448 StringBuilder implicitPerms = null;
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002449 for (int ip=0; ip<NP; ip++) {
2450 final PackageParser.NewPermissionInfo npi
2451 = PackageParser.NEW_PERMISSIONS[ip];
2452 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
2453 break;
2454 }
2455 if (!pkg.requestedPermissions.contains(npi.name)) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002456 if (implicitPerms == null) {
2457 implicitPerms = new StringBuilder(128);
2458 implicitPerms.append(pkg.packageName);
2459 implicitPerms.append(": compat added ");
2460 } else {
2461 implicitPerms.append(' ');
2462 }
2463 implicitPerms.append(npi.name);
Dianne Hackborna96cbb42009-05-13 15:06:13 -07002464 pkg.requestedPermissions.add(npi.name);
2465 }
Dianne Hackborn851a5412009-05-08 12:06:44 -07002466 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002467 if (implicitPerms != null) {
Kenny Rootd2d29252011-08-08 11:27:57 -07002468 Slog.i(TAG, implicitPerms.toString());
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002469 }
Dianne Hackborn79245122012-03-12 10:51:26 -07002470
2471 final int NS = PackageParser.SPLIT_PERMISSIONS.length;
2472 for (int is=0; is<NS; is++) {
2473 final PackageParser.SplitPermissionInfo spi
2474 = PackageParser.SPLIT_PERMISSIONS[is];
Dianne Hackborn31b0e0e2012-04-05 19:33:30 -07002475 if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
2476 || !pkg.requestedPermissions.contains(spi.rootPerm)) {
Dianne Hackborn5e4705a2012-04-06 12:55:53 -07002477 continue;
Dianne Hackborn79245122012-03-12 10:51:26 -07002478 }
2479 for (int in=0; in<spi.newPerms.length; in++) {
2480 final String perm = spi.newPerms[in];
2481 if (!pkg.requestedPermissions.contains(perm)) {
2482 pkg.requestedPermissions.add(perm);
Dianne Hackborn79245122012-03-12 10:51:26 -07002483 }
2484 }
2485 }
2486
Dianne Hackborn723738c2009-06-25 19:48:04 -07002487 if (supportsSmallScreens < 0 || (supportsSmallScreens > 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_SMALL_SCREENS;
2491 }
2492 if (supportsNormalScreens != 0) {
2493 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
2494 }
2495 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
2496 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002497 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07002498 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
2499 }
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07002500 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
2501 && pkg.applicationInfo.targetSdkVersion
2502 >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
2503 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
2504 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002505 if (resizeable < 0 || (resizeable > 0
2506 && pkg.applicationInfo.targetSdkVersion
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002507 >= android.os.Build.VERSION_CODES.DONUT)) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07002508 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
2509 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07002510 if (anyDensity < 0 || (anyDensity > 0
2511 && pkg.applicationInfo.targetSdkVersion
2512 >= android.os.Build.VERSION_CODES.DONUT)) {
2513 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
Mitsuru Oshima8d112672009-04-27 12:01:23 -07002514 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07002515
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002516 // At this point we can check if an application is not supporting densities and hence
2517 // cannot be windowed / resized. Note that an SDK version of 0 is common for
2518 // pre-Doughnut applications.
2519 if (pkg.applicationInfo.usesCompatibilityMode()) {
Winson Chungd3395382016-12-13 11:49:09 -08002520 adjustPackageToBeUnresizeableAndUnpipable(pkg);
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002521 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002522 return pkg;
2523 }
2524
Todd Leeea2f3be2017-03-16 14:00:52 -07002525 private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
2526
2527 if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
2528 if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
2529 // malformed condition - incomplete
2530 Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName
2531 + "=" + propValue + "' - require both requiredSystemPropertyName"
2532 + " AND requiredSystemPropertyValue to be specified.");
2533 return false;
2534 }
2535 // no valid condition set - so no exclusion criteria, overlay will be included.
2536 return true;
2537 }
2538
2539 // check property value - make sure it is both set and equal to expected value
2540 final String currValue = SystemProperties.get(propName);
2541 return (currValue != null && currValue.equals(propValue));
2542 }
2543
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002544 /**
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002545 * This is a pre-density application which will get scaled - instead of being pixel perfect.
2546 * This type of application is not resizable.
2547 *
2548 * @param pkg The package which needs to be marked as unresizable.
2549 */
Winson Chungd3395382016-12-13 11:49:09 -08002550 private void adjustPackageToBeUnresizeableAndUnpipable(Package pkg) {
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002551 for (Activity a : pkg.activities) {
2552 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -08002553 a.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE;
skuhne@google.com7e85eb02017-01-04 13:49:54 -08002554 }
2555 }
2556
2557 /**
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002558 * Computes the targetSdkVersion to use at runtime. If the package is not
2559 * compatible with this platform, populates {@code outError[0]} with an
2560 * error message.
2561 * <p>
2562 * If {@code targetCode} is not specified, e.g. the value is {@code null},
2563 * then the {@code targetVers} will be returned unmodified.
2564 * <p>
2565 * Otherwise, the behavior varies based on whether the current platform
2566 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2567 * has length > 0:
2568 * <ul>
2569 * <li>If this is a pre-release platform and the value specified by
2570 * {@code targetCode} is contained within the array of allowed pre-release
2571 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2572 * <li>If this is a released platform, this method will return -1 to
2573 * indicate that the package is not compatible with this platform.
2574 * </ul>
2575 *
2576 * @param targetVers targetSdkVersion number, if specified in the
2577 * application manifest, or 0 otherwise
2578 * @param targetCode targetSdkVersion code, if specified in the application
2579 * manifest, or {@code null} otherwise
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002580 * @param platformSdkCodenames array of allowed pre-release SDK codenames
2581 * for this platform
2582 * @param outError output array to populate with error, if applicable
Patrick Baumannccb20b82018-01-08 13:22:46 -08002583 * @param forceCurrentDev if development target code is not available, use the current
2584 * development version by default.
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002585 * @return the targetSdkVersion to use at runtime, or -1 if the package is
2586 * not compatible with this platform
2587 * @hide Exposed for unit testing only.
2588 */
2589 @TestApi
2590 public static int computeTargetSdkVersion(@IntRange(from = 0) int targetVers,
Patrick Baumannccb20b82018-01-08 13:22:46 -08002591 @Nullable String targetCode, @NonNull String[] platformSdkCodenames,
2592 @NonNull String[] outError, boolean forceCurrentDev) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002593 // If it's a release SDK, return the version number unmodified.
2594 if (targetCode == null) {
2595 return targetVers;
2596 }
2597
2598 // If it's a pre-release SDK and the codename matches this platform, it
2599 // definitely targets this SDK.
Patrick Baumannccb20b82018-01-08 13:22:46 -08002600 if (ArrayUtils.contains(platformSdkCodenames, targetCode) || forceCurrentDev) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -05002601 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2602 }
2603
2604 // Otherwise, we're looking at an incompatible pre-release SDK.
2605 if (platformSdkCodenames.length > 0) {
2606 outError[0] = "Requires development platform " + targetCode
2607 + " (current platform is any of "
2608 + Arrays.toString(platformSdkCodenames) + ")";
2609 } else {
2610 outError[0] = "Requires development platform " + targetCode
2611 + " but this is a release platform.";
2612 }
2613 return -1;
2614 }
2615
2616 /**
2617 * Computes the minSdkVersion to use at runtime. If the package is not
2618 * compatible with this platform, populates {@code outError[0]} with an
2619 * error message.
2620 * <p>
2621 * If {@code minCode} is not specified, e.g. the value is {@code null},
2622 * then behavior varies based on the {@code platformSdkVersion}:
2623 * <ul>
2624 * <li>If the platform SDK version is greater than or equal to the
2625 * {@code minVers}, returns the {@code mniVers} unmodified.
2626 * <li>Otherwise, returns -1 to indicate that the package is not
2627 * compatible with this platform.
2628 * </ul>
2629 * <p>
2630 * Otherwise, the behavior varies based on whether the current platform
2631 * is a pre-release version, e.g. the {@code platformSdkCodenames} array
2632 * has length > 0:
2633 * <ul>
2634 * <li>If this is a pre-release platform and the value specified by
2635 * {@code targetCode} is contained within the array of allowed pre-release
2636 * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
2637 * <li>If this is a released platform, this method will return -1 to
2638 * indicate that the package is not compatible with this platform.
2639 * </ul>
2640 *
2641 * @param minVers minSdkVersion number, if specified in the application
2642 * manifest, or 1 otherwise
2643 * @param minCode minSdkVersion code, if specified in the application
2644 * manifest, or {@code null} otherwise
2645 * @param platformSdkVersion platform SDK version number, typically
2646 * Build.VERSION.SDK_INT
2647 * @param platformSdkCodenames array of allowed prerelease SDK codenames
2648 * for this platform
2649 * @param outError output array to populate with error, if applicable
2650 * @return the minSdkVersion to use at runtime, or -1 if the package is not
2651 * compatible with this platform
2652 * @hide Exposed for unit testing only.
2653 */
2654 @TestApi
2655 public static int computeMinSdkVersion(@IntRange(from = 1) int minVers,
2656 @Nullable String minCode, @IntRange(from = 1) int platformSdkVersion,
2657 @NonNull String[] platformSdkCodenames, @NonNull String[] outError) {
2658 // If it's a release SDK, make sure we meet the minimum SDK requirement.
2659 if (minCode == null) {
2660 if (minVers <= platformSdkVersion) {
2661 return minVers;
2662 }
2663
2664 // We don't meet the minimum SDK requirement.
2665 outError[0] = "Requires newer sdk version #" + minVers
2666 + " (current version is #" + platformSdkVersion + ")";
2667 return -1;
2668 }
2669
2670 // If it's a pre-release SDK and the codename matches this platform, we
2671 // definitely meet the minimum SDK requirement.
2672 if (ArrayUtils.contains(platformSdkCodenames, minCode)) {
2673 return Build.VERSION_CODES.CUR_DEVELOPMENT;
2674 }
2675
2676 // Otherwise, we're looking at an incompatible pre-release SDK.
2677 if (platformSdkCodenames.length > 0) {
2678 outError[0] = "Requires development platform " + minCode
2679 + " (current platform is any of "
2680 + Arrays.toString(platformSdkCodenames) + ")";
2681 } else {
2682 outError[0] = "Requires development platform " + minCode
2683 + " but this is a release platform.";
2684 }
2685 return -1;
2686 }
2687
Todd Kennedy27c24fb2015-09-17 16:49:25 -07002688 private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) {
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002689 FeatureInfo fi = new FeatureInfo();
2690 TypedArray sa = res.obtainAttributes(attrs,
2691 com.android.internal.R.styleable.AndroidManifestUsesFeature);
2692 // Note: don't allow this value to be a reference to a resource
2693 // that may change.
2694 fi.name = sa.getNonResourceString(
2695 com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
Jeff Sharkey115d2c12016-02-15 17:25:57 -07002696 fi.version = sa.getInt(
2697 com.android.internal.R.styleable.AndroidManifestUsesFeature_version, 0);
Adam Lesinskid3edfde2014-08-08 17:32:44 -07002698 if (fi.name == null) {
2699 fi.reqGlEsVersion = sa.getInt(
2700 com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
2701 FeatureInfo.GL_ES_VERSION_UNDEFINED);
2702 }
2703 if (sa.getBoolean(
2704 com.android.internal.R.styleable.AndroidManifestUsesFeature_required, true)) {
2705 fi.flags |= FeatureInfo.FLAG_REQUIRED;
2706 }
2707 sa.recycle();
2708 return fi;
2709 }
2710
Svet Ganov67882122016-12-11 16:36:34 -08002711 private boolean parseUsesStaticLibrary(Package pkg, Resources res, XmlResourceParser parser,
2712 String[] outError) throws XmlPullParserException, IOException {
2713 TypedArray sa = res.obtainAttributes(parser,
2714 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary);
2715
2716 // Note: don't allow this value to be a reference to a resource that may change.
2717 String lname = sa.getNonResourceString(
2718 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
2719 final int version = sa.getInt(
2720 com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary_version, -1);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002721 String certSha256Digest = sa.getNonResourceString(com.android.internal.R.styleable
Svet Ganov67882122016-12-11 16:36:34 -08002722 .AndroidManifestUsesStaticLibrary_certDigest);
2723 sa.recycle();
2724
2725 // Since an APK providing a static shared lib can only provide the lib - fail if malformed
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002726 if (lname == null || version < 0 || certSha256Digest == null) {
Svet Ganov67882122016-12-11 16:36:34 -08002727 outError[0] = "Bad uses-static-library declaration name: " + lname + " version: "
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002728 + version + " certDigest" + certSha256Digest;
Svet Ganov67882122016-12-11 16:36:34 -08002729 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2730 XmlUtils.skipCurrentTag(parser);
2731 return false;
2732 }
2733
2734 // Can depend only on one version of the same library
2735 if (pkg.usesStaticLibraries != null && pkg.usesStaticLibraries.contains(lname)) {
2736 outError[0] = "Depending on multiple versions of static library " + lname;
2737 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2738 XmlUtils.skipCurrentTag(parser);
2739 return false;
2740 }
2741
2742 lname = lname.intern();
2743 // We allow ":" delimiters in the SHA declaration as this is the format
2744 // emitted by the certtool making it easy for developers to copy/paste.
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002745 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2746
2747 // Fot apps targeting O-MR1 we require explicit enumeration of all certs.
2748 String[] additionalCertSha256Digests = EmptyArray.STRING;
2749 if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.O) {
2750 additionalCertSha256Digests = parseAdditionalCertificates(res, parser, outError);
2751 if (additionalCertSha256Digests == null) {
2752 return false;
2753 }
2754 } else {
2755 XmlUtils.skipCurrentTag(parser);
2756 }
2757
2758 final String[] certSha256Digests = new String[additionalCertSha256Digests.length + 1];
2759 certSha256Digests[0] = certSha256Digest;
2760 System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests,
2761 1, additionalCertSha256Digests.length);
2762
Svet Ganov67882122016-12-11 16:36:34 -08002763 pkg.usesStaticLibraries = ArrayUtils.add(pkg.usesStaticLibraries, lname);
Dianne Hackborn3accca02013-09-20 09:32:11 -07002764 pkg.usesStaticLibrariesVersions = ArrayUtils.appendLong(
Svet Ganov8a10ef52017-02-16 20:58:09 -08002765 pkg.usesStaticLibrariesVersions, version, true);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002766 pkg.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String[].class,
2767 pkg.usesStaticLibrariesCertDigests, certSha256Digests, true);
Svet Ganov67882122016-12-11 16:36:34 -08002768
2769 return true;
2770 }
2771
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07002772 private String[] parseAdditionalCertificates(Resources resources, XmlResourceParser parser,
2773 String[] outError) throws XmlPullParserException, IOException {
2774 String[] certSha256Digests = EmptyArray.STRING;
2775
2776 int outerDepth = parser.getDepth();
2777 int type;
2778 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2779 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2780 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2781 continue;
2782 }
2783
2784 final String nodeName = parser.getName();
2785 if (nodeName.equals("additional-certificate")) {
2786 final TypedArray sa = resources.obtainAttributes(parser, com.android.internal.
2787 R.styleable.AndroidManifestAdditionalCertificate);
2788 String certSha256Digest = sa.getNonResourceString(com.android.internal.
2789 R.styleable.AndroidManifestAdditionalCertificate_certDigest);
2790 sa.recycle();
2791
2792 if (TextUtils.isEmpty(certSha256Digest)) {
2793 outError[0] = "Bad additional-certificate declaration with empty"
2794 + " certDigest:" + certSha256Digest;
2795 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
2796 XmlUtils.skipCurrentTag(parser);
2797 sa.recycle();
2798 return null;
2799 }
2800
2801 // We allow ":" delimiters in the SHA declaration as this is the format
2802 // emitted by the certtool making it easy for developers to copy/paste.
2803 certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
2804 certSha256Digests = ArrayUtils.appendElement(String.class,
2805 certSha256Digests, certSha256Digest);
2806 } else {
2807 XmlUtils.skipCurrentTag(parser);
2808 }
2809 }
2810
2811 return certSha256Digests;
2812 }
2813
Svet Ganov354cd3c2015-12-17 11:35:04 -08002814 private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
2815 throws XmlPullParserException, IOException {
2816 TypedArray sa = res.obtainAttributes(parser,
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002817 com.android.internal.R.styleable.AndroidManifestUsesPermission);
2818
2819 // Note: don't allow this value to be a reference to a resource
2820 // that may change.
2821 String name = sa.getNonResourceString(
2822 com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002823
Christopher Tatefb0676a2013-09-16 16:34:52 -07002824 int maxSdkVersion = 0;
2825 TypedValue val = sa.peekValue(
2826 com.android.internal.R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
2827 if (val != null) {
2828 if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
2829 maxSdkVersion = val.data;
2830 }
2831 }
2832
Dianne Hackborncd154e92017-02-28 17:37:35 -08002833 final String requiredFeature = sa.getNonConfigurationString(
2834 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredFeature, 0);
2835
2836 final String requiredNotfeature = sa.getNonConfigurationString(
2837 com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);
2838
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002839 sa.recycle();
2840
Dianne Hackborncd154e92017-02-28 17:37:35 -08002841 XmlUtils.skipCurrentTag(parser);
2842
2843 if (name == null) {
2844 return true;
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002845 }
2846
Dianne Hackborncd154e92017-02-28 17:37:35 -08002847 if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) {
2848 return true;
2849 }
2850
2851 // Only allow requesting this permission if the platform supports the given feature.
2852 if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(requiredFeature)) {
2853 return true;
2854 }
2855
2856 // Only allow requesting this permission if the platform doesn't support the given feature.
2857 if (requiredNotfeature != null && mCallback != null
2858 && mCallback.hasFeature(requiredNotfeature)) {
2859 return true;
2860 }
2861
2862 int index = pkg.requestedPermissions.indexOf(name);
2863 if (index == -1) {
2864 pkg.requestedPermissions.add(name.intern());
2865 } else {
2866 Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
2867 + name + " in package: " + pkg.packageName + " at: "
2868 + parser.getPositionDescription());
2869 }
2870
Nick Kralevich73f2d3c2013-04-04 14:38:13 -07002871 return true;
2872 }
2873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002874 private static String buildClassName(String pkg, CharSequence clsSeq,
2875 String[] outError) {
2876 if (clsSeq == null || clsSeq.length() <= 0) {
2877 outError[0] = "Empty class name in package " + pkg;
2878 return null;
2879 }
2880 String cls = clsSeq.toString();
2881 char c = cls.charAt(0);
2882 if (c == '.') {
Narayan Kamath07ac1442017-02-10 15:08:07 +00002883 return pkg + cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002884 }
2885 if (cls.indexOf('.') < 0) {
2886 StringBuilder b = new StringBuilder(pkg);
2887 b.append('.');
2888 b.append(cls);
Narayan Kamath07ac1442017-02-10 15:08:07 +00002889 return b.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002890 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002891 return cls;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002892 }
2893
2894 private static String buildCompoundName(String pkg,
2895 CharSequence procSeq, String type, String[] outError) {
2896 String proc = procSeq.toString();
2897 char c = proc.charAt(0);
2898 if (pkg != null && c == ':') {
2899 if (proc.length() < 2) {
2900 outError[0] = "Bad " + type + " name " + proc + " in package " + pkg
2901 + ": must be at least two characters";
2902 return null;
2903 }
2904 String subName = proc.substring(1);
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002905 String nameError = validateName(subName, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002906 if (nameError != null) {
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 pkg + proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002912 }
Jeff Sharkey4f5e8b32015-06-11 19:13:37 -07002913 String nameError = validateName(proc, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002914 if (nameError != null && !"system".equals(proc)) {
2915 outError[0] = "Invalid " + type + " name " + proc + " in package "
2916 + pkg + ": " + nameError;
2917 return null;
2918 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00002919 return proc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002920 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07002921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002922 private static String buildProcessName(String pkg, String defProc,
2923 CharSequence procSeq, int flags, String[] separateProcesses,
2924 String[] outError) {
2925 if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) {
2926 return defProc != null ? defProc : pkg;
2927 }
2928 if (separateProcesses != null) {
2929 for (int i=separateProcesses.length-1; i>=0; i--) {
2930 String sp = separateProcesses[i];
2931 if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) {
2932 return pkg;
2933 }
2934 }
2935 }
2936 if (procSeq == null || procSeq.length() <= 0) {
2937 return defProc;
2938 }
Makoto Onuki812d188a2017-08-07 09:58:23 -07002939 return TextUtils.safeIntern(buildCompoundName(pkg, procSeq, "process", outError));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002940 }
2941
2942 private static String buildTaskAffinityName(String pkg, String defProc,
2943 CharSequence procSeq, String[] outError) {
2944 if (procSeq == null) {
2945 return defProc;
2946 }
2947 if (procSeq.length() <= 0) {
2948 return null;
2949 }
2950 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
2951 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002952
dcashman989eb3712014-06-17 12:56:12 -07002953 private boolean parseKeySets(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08002954 XmlResourceParser parser, String[] outError)
Geremy Condraf1bcca82013-01-07 22:35:24 -08002955 throws XmlPullParserException, IOException {
dcashman989eb3712014-06-17 12:56:12 -07002956 // we've encountered the 'key-sets' tag
Geremy Condraf1bcca82013-01-07 22:35:24 -08002957 // all the keys and keysets that we want must be defined here
2958 // so we're going to iterate over the parser and pull out the things we want
2959 int outerDepth = parser.getDepth();
dcashman989eb3712014-06-17 12:56:12 -07002960 int currentKeySetDepth = -1;
Geremy Condraf1bcca82013-01-07 22:35:24 -08002961 int type;
dcashman989eb3712014-06-17 12:56:12 -07002962 String currentKeySet = null;
2963 ArrayMap<String, PublicKey> publicKeys = new ArrayMap<String, PublicKey>();
2964 ArraySet<String> upgradeKeySets = new ArraySet<String>();
2965 ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<String, ArraySet<String>>();
2966 ArraySet<String> improperKeySets = new ArraySet<String>();
Geremy Condraf1bcca82013-01-07 22:35:24 -08002967 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2968 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2969 if (type == XmlPullParser.END_TAG) {
dcashman989eb3712014-06-17 12:56:12 -07002970 if (parser.getDepth() == currentKeySetDepth) {
2971 currentKeySet = null;
2972 currentKeySetDepth = -1;
Kenny Root37dca152013-07-10 14:01:49 -07002973 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08002974 continue;
2975 }
dcashman989eb3712014-06-17 12:56:12 -07002976 String tagName = parser.getName();
2977 if (tagName.equals("key-set")) {
2978 if (currentKeySet != null) {
dcashman5db0cd42015-05-22 15:24:40 -07002979 outError[0] = "Improperly nested 'key-set' tag at "
2980 + parser.getPositionDescription();
2981 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002982 return false;
2983 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002984 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07002985 com.android.internal.R.styleable.AndroidManifestKeySet);
2986 final String keysetName = sa.getNonResourceString(
2987 com.android.internal.R.styleable.AndroidManifestKeySet_name);
2988 definedKeySets.put(keysetName, new ArraySet<String>());
2989 currentKeySet = keysetName;
2990 currentKeySetDepth = parser.getDepth();
2991 sa.recycle();
2992 } else if (tagName.equals("public-key")) {
2993 if (currentKeySet == null) {
dcashman5db0cd42015-05-22 15:24:40 -07002994 outError[0] = "Improperly nested 'key-set' tag at "
2995 + parser.getPositionDescription();
2996 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07002997 return false;
2998 }
Svet Ganov354cd3c2015-12-17 11:35:04 -08002999 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003000 com.android.internal.R.styleable.AndroidManifestPublicKey);
3001 final String publicKeyName = sa.getNonResourceString(
3002 com.android.internal.R.styleable.AndroidManifestPublicKey_name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003003 final String encodedKey = sa.getNonResourceString(
dcashman989eb3712014-06-17 12:56:12 -07003004 com.android.internal.R.styleable.AndroidManifestPublicKey_value);
3005 if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
dcashman5db0cd42015-05-22 15:24:40 -07003006 outError[0] = "'public-key' " + publicKeyName + " must define a public-key value"
3007 + " on first use at " + parser.getPositionDescription();
3008 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Kenny Root37dca152013-07-10 14:01:49 -07003009 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003010 return false;
3011 } else if (encodedKey != null) {
3012 PublicKey currentKey = parsePublicKey(encodedKey);
3013 if (currentKey == null) {
3014 Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
3015 + parser.getPositionDescription() + " key-set " + currentKeySet
3016 + " will not be added to the package's defined key-sets.");
3017 sa.recycle();
3018 improperKeySets.add(currentKeySet);
3019 XmlUtils.skipCurrentTag(parser);
3020 continue;
3021 }
3022 if (publicKeys.get(publicKeyName) == null
3023 || publicKeys.get(publicKeyName).equals(currentKey)) {
3024
3025 /* public-key first definition, or matches old definition */
3026 publicKeys.put(publicKeyName, currentKey);
3027 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003028 outError[0] = "Value of 'public-key' " + publicKeyName
dcashman989eb3712014-06-17 12:56:12 -07003029 + " conflicts with previously defined value at "
dcashman5db0cd42015-05-22 15:24:40 -07003030 + parser.getPositionDescription();
3031 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003032 sa.recycle();
3033 return false;
3034 }
Kenny Root37dca152013-07-10 14:01:49 -07003035 }
dcashman989eb3712014-06-17 12:56:12 -07003036 definedKeySets.get(currentKeySet).add(publicKeyName);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003037 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003038 XmlUtils.skipCurrentTag(parser);
3039 } else if (tagName.equals("upgrade-key-set")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003040 final TypedArray sa = res.obtainAttributes(parser,
dcashman989eb3712014-06-17 12:56:12 -07003041 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet);
3042 String name = sa.getNonResourceString(
3043 com.android.internal.R.styleable.AndroidManifestUpgradeKeySet_name);
3044 upgradeKeySets.add(name);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003045 sa.recycle();
dcashman989eb3712014-06-17 12:56:12 -07003046 XmlUtils.skipCurrentTag(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -08003047 } else if (RIGID_PARSER) {
dcashman5db0cd42015-05-22 15:24:40 -07003048 outError[0] = "Bad element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003049 + " at " + mArchiveSourcePath + " "
dcashman5db0cd42015-05-22 15:24:40 -07003050 + parser.getPositionDescription();
3051 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Geremy Condraf1bcca82013-01-07 22:35:24 -08003052 return false;
3053 } else {
dcashman989eb3712014-06-17 12:56:12 -07003054 Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
Geremy Condraf1bcca82013-01-07 22:35:24 -08003055 + " at " + mArchiveSourcePath + " "
3056 + parser.getPositionDescription());
3057 XmlUtils.skipCurrentTag(parser);
3058 continue;
3059 }
3060 }
dcashman989eb3712014-06-17 12:56:12 -07003061 Set<String> publicKeyNames = publicKeys.keySet();
3062 if (publicKeyNames.removeAll(definedKeySets.keySet())) {
dcashman5db0cd42015-05-22 15:24:40 -07003063 outError[0] = "Package" + owner.packageName + " AndroidManifext.xml "
3064 + "'key-set' and 'public-key' names must be distinct.";
3065 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003066 return false;
3067 }
3068 owner.mKeySetMapping = new ArrayMap<String, ArraySet<PublicKey>>();
3069 for (ArrayMap.Entry<String, ArraySet<String>> e: definedKeySets.entrySet()) {
3070 final String keySetName = e.getKey();
3071 if (e.getValue().size() == 0) {
3072 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3073 + "'key-set' " + keySetName + " has no valid associated 'public-key'."
3074 + " Not including in package's defined key-sets.");
3075 continue;
3076 } else if (improperKeySets.contains(keySetName)) {
3077 Slog.w(TAG, "Package" + owner.packageName + " AndroidManifext.xml "
3078 + "'key-set' " + keySetName + " contained improper 'public-key'"
3079 + " tags. Not including in package's defined key-sets.");
3080 continue;
3081 }
3082 owner.mKeySetMapping.put(keySetName, new ArraySet<PublicKey>());
3083 for (String s : e.getValue()) {
3084 owner.mKeySetMapping.get(keySetName).add(publicKeys.get(s));
Geremy Condraf1bcca82013-01-07 22:35:24 -08003085 }
3086 }
dcashman989eb3712014-06-17 12:56:12 -07003087 if (owner.mKeySetMapping.keySet().containsAll(upgradeKeySets)) {
3088 owner.mUpgradeKeySets = upgradeKeySets;
3089 } else {
dcashman5db0cd42015-05-22 15:24:40 -07003090 outError[0] ="Package" + owner.packageName + " AndroidManifext.xml "
3091 + "does not define all 'upgrade-key-set's .";
3092 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
dcashman989eb3712014-06-17 12:56:12 -07003093 return false;
3094 }
Geremy Condraf1bcca82013-01-07 22:35:24 -08003095 return true;
3096 }
3097
Dianne Hackborncd154e92017-02-28 17:37:35 -08003098 private boolean parsePermissionGroup(Package owner, int flags, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003099 XmlResourceParser parser, String[] outError)
3100 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003101 PermissionGroup perm = new PermissionGroup(owner);
3102
Svet Ganov354cd3c2015-12-17 11:35:04 -08003103 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003104 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003105 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003106 "<permission-group>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003107 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
3108 com.android.internal.R.styleable.AndroidManifestPermissionGroup_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003109 com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003110 com.android.internal.R.styleable.AndroidManifestPermissionGroup_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003111 com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo,
3112 com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003113 sa.recycle();
3114 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003115 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003116 }
3117
3118 perm.info.descriptionRes = sa.getResourceId(
3119 com.android.internal.R.styleable.AndroidManifestPermissionGroup_description,
3120 0);
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003121 perm.info.requestRes = sa.getResourceId(
3122 com.android.internal.R.styleable.AndroidManifestPermissionGroup_request, 0);
Dianne Hackborn7454d3b2012-09-12 17:22:00 -07003123 perm.info.flags = sa.getInt(
3124 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
Dianne Hackbornfd5015b2012-04-30 16:33:56 -07003125 perm.info.priority = sa.getInt(
3126 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003127
3128 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003129
Svet Ganov354cd3c2015-12-17 11:35:04 -08003130 if (!parseAllMetaData(res, parser, "<permission-group>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003131 outError)) {
3132 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003133 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003134 }
3135
3136 owner.permissionGroups.add(perm);
3137
Dianne Hackborncd154e92017-02-28 17:37:35 -08003138 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003139 }
3140
Dianne Hackborncd154e92017-02-28 17:37:35 -08003141 private boolean parsePermission(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003142 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003143 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003144
Svet Ganov354cd3c2015-12-17 11:35:04 -08003145 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003146 com.android.internal.R.styleable.AndroidManifestPermission);
3147
Dianne Hackborncd154e92017-02-28 17:37:35 -08003148 Permission perm = new Permission(owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003149 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003150 "<permission>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003151 com.android.internal.R.styleable.AndroidManifestPermission_name,
3152 com.android.internal.R.styleable.AndroidManifestPermission_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003153 com.android.internal.R.styleable.AndroidManifestPermission_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003154 com.android.internal.R.styleable.AndroidManifestPermission_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003155 com.android.internal.R.styleable.AndroidManifestPermission_logo,
3156 com.android.internal.R.styleable.AndroidManifestPermission_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003157 sa.recycle();
3158 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003159 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003160 }
3161
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003162 // Note: don't allow this value to be a reference to a resource
3163 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003164 perm.info.group = sa.getNonResourceString(
3165 com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup);
3166 if (perm.info.group != null) {
3167 perm.info.group = perm.info.group.intern();
3168 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003170 perm.info.descriptionRes = sa.getResourceId(
3171 com.android.internal.R.styleable.AndroidManifestPermission_description,
3172 0);
3173
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003174 perm.info.requestRes = sa.getResourceId(
3175 com.android.internal.R.styleable.AndroidManifestPermission_request, 0);
3176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003177 perm.info.protectionLevel = sa.getInt(
3178 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
3179 PermissionInfo.PROTECTION_NORMAL);
3180
Dianne Hackborn2ca2c872012-09-16 16:03:36 -07003181 perm.info.flags = sa.getInt(
3182 com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
3183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003184 sa.recycle();
Dianne Hackborne639da72012-02-21 15:11:13 -08003185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003186 if (perm.info.protectionLevel == -1) {
3187 outError[0] = "<permission> does not specify protectionLevel";
3188 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003189 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003190 }
Dianne Hackborne639da72012-02-21 15:11:13 -08003191
3192 perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel);
3193
3194 if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_FLAGS) != 0) {
Todd Kennedyc247fa12017-06-02 10:29:22 -07003195 if ( (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_INSTANT) == 0
Chad Brubakera5d70a12017-03-23 11:04:50 -07003196 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0
Chad Brubakerc19706a2016-10-13 15:44:59 -07003197 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) !=
Dianne Hackborne639da72012-02-21 15:11:13 -08003198 PermissionInfo.PROTECTION_SIGNATURE) {
Todd Kennedyc247fa12017-06-02 10:29:22 -07003199 outError[0] = "<permission> protectionLevel specifies a non-instnat flag but is "
Dianne Hackborne639da72012-02-21 15:11:13 -08003200 + "not based on signature type";
3201 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003202 return false;
Dianne Hackborne639da72012-02-21 15:11:13 -08003203 }
3204 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003205
Svet Ganov354cd3c2015-12-17 11:35:04 -08003206 if (!parseAllMetaData(res, parser, "<permission>", perm, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003207 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003208 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003209 }
3210
3211 owner.permissions.add(perm);
3212
Dianne Hackborncd154e92017-02-28 17:37:35 -08003213 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003214 }
3215
Dianne Hackborncd154e92017-02-28 17:37:35 -08003216 private boolean parsePermissionTree(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003217 XmlResourceParser parser, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003218 throws XmlPullParserException, IOException {
3219 Permission perm = new Permission(owner);
3220
Svet Ganov354cd3c2015-12-17 11:35:04 -08003221 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003222 com.android.internal.R.styleable.AndroidManifestPermissionTree);
3223
3224 if (!parsePackageItemInfo(owner, perm.info, outError,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003225 "<permission-tree>", sa, true /*nameRequired*/,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003226 com.android.internal.R.styleable.AndroidManifestPermissionTree_name,
3227 com.android.internal.R.styleable.AndroidManifestPermissionTree_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003228 com.android.internal.R.styleable.AndroidManifestPermissionTree_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003229 com.android.internal.R.styleable.AndroidManifestPermissionTree_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003230 com.android.internal.R.styleable.AndroidManifestPermissionTree_logo,
3231 com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003232 sa.recycle();
3233 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003234 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003235 }
3236
3237 sa.recycle();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003239 int index = perm.info.name.indexOf('.');
3240 if (index > 0) {
3241 index = perm.info.name.indexOf('.', index+1);
3242 }
3243 if (index < 0) {
3244 outError[0] = "<permission-tree> name has less than three segments: "
3245 + perm.info.name;
3246 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003247 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248 }
3249
3250 perm.info.descriptionRes = 0;
Philip P. Moltmann27ffeb32017-07-06 13:54:46 -07003251 perm.info.requestRes = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003252 perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
3253 perm.tree = true;
3254
Svet Ganov354cd3c2015-12-17 11:35:04 -08003255 if (!parseAllMetaData(res, parser, "<permission-tree>", perm,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003256 outError)) {
3257 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
Dianne Hackborncd154e92017-02-28 17:37:35 -08003258 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003259 }
3260
3261 owner.permissions.add(perm);
3262
Dianne Hackborncd154e92017-02-28 17:37:35 -08003263 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003264 }
3265
3266 private Instrumentation parseInstrumentation(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003267 XmlResourceParser parser, String[] outError)
3268 throws XmlPullParserException, IOException {
3269 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 com.android.internal.R.styleable.AndroidManifestInstrumentation);
3271
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003272 if (mParseInstrumentationArgs == null) {
3273 mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
3274 com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
3275 com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
Adam Powell81cd2e92010-04-21 16:35:18 -07003276 com.android.internal.R.styleable.AndroidManifestInstrumentation_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003277 com.android.internal.R.styleable.AndroidManifestInstrumentation_roundIcon,
Jose Limaf78e3122014-03-06 12:13:15 -08003278 com.android.internal.R.styleable.AndroidManifestInstrumentation_logo,
3279 com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003280 mParseInstrumentationArgs.tag = "<instrumentation>";
3281 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003282
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003283 mParseInstrumentationArgs.sa = sa;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003284
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003285 Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
3286 new InstrumentationInfo());
3287 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003288 sa.recycle();
3289 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3290 return null;
3291 }
3292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003293 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003294 // Note: don't allow this value to be a reference to a resource
3295 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003296 str = sa.getNonResourceString(
3297 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
3298 a.info.targetPackage = str != null ? str.intern() : null;
3299
Dianne Hackborn34041732017-01-31 15:27:13 -08003300 str = sa.getNonResourceString(
Dianne Hackborn1be53542017-04-28 13:36:00 -07003301 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetProcesses);
3302 a.info.targetProcesses = str != null ? str.intern() : null;
Dianne Hackborn34041732017-01-31 15:27:13 -08003303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003304 a.info.handleProfiling = sa.getBoolean(
3305 com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling,
3306 false);
3307
3308 a.info.functionalTest = sa.getBoolean(
3309 com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest,
3310 false);
3311
3312 sa.recycle();
3313
3314 if (a.info.targetPackage == null) {
3315 outError[0] = "<instrumentation> does not specify targetPackage";
3316 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3317 return null;
3318 }
3319
Svet Ganov354cd3c2015-12-17 11:35:04 -08003320 if (!parseAllMetaData(res, parser, "<instrumentation>", a,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003321 outError)) {
3322 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3323 return null;
3324 }
3325
3326 owner.instrumentation.add(a);
3327
3328 return a;
3329 }
3330
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003331 /**
3332 * Parse the {@code application} XML tree at the current parse location in a
3333 * <em>base APK</em> manifest.
3334 * <p>
3335 * When adding new features, carefully consider if they should also be
3336 * supported by split APKs.
3337 */
3338 private boolean parseBaseApplication(Package owner, Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08003339 XmlResourceParser parser, int flags, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003340 throws XmlPullParserException, IOException {
3341 final ApplicationInfo ai = owner.applicationInfo;
3342 final String pkgName = owner.applicationInfo.packageName;
3343
Svet Ganov354cd3c2015-12-17 11:35:04 -08003344 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003345 com.android.internal.R.styleable.AndroidManifestApplication);
3346
Todd Kennedybb8a42d2016-06-02 14:13:56 -07003347 if (!parsePackageItemInfo(owner, ai, outError,
3348 "<application>", sa, false /*nameRequired*/,
3349 com.android.internal.R.styleable.AndroidManifestApplication_name,
3350 com.android.internal.R.styleable.AndroidManifestApplication_label,
3351 com.android.internal.R.styleable.AndroidManifestApplication_icon,
3352 com.android.internal.R.styleable.AndroidManifestApplication_roundIcon,
3353 com.android.internal.R.styleable.AndroidManifestApplication_logo,
3354 com.android.internal.R.styleable.AndroidManifestApplication_banner)) {
3355 sa.recycle();
3356 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3357 return false;
3358 }
3359
3360 if (ai.name != null) {
Todd Kennedyafb52692016-08-22 15:44:00 -07003361 ai.className = ai.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003362 }
3363
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003364 String manageSpaceActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003365 com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
3366 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003367 if (manageSpaceActivity != null) {
3368 ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
3369 outError);
3370 }
3371
Christopher Tate181fafa2009-05-14 11:12:14 -07003372 boolean allowBackup = sa.getBoolean(
3373 com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
3374 if (allowBackup) {
3375 ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
Christopher Tate5e1ab332009-09-01 20:32:49 -07003376
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003377 // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
3378 // and restoreAnyVersion are only relevant if backup is possible for the
3379 // given application.
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003380 String backupAgent = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003381 com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
3382 Configuration.NATIVE_CONFIG_VERSION);
Christopher Tate181fafa2009-05-14 11:12:14 -07003383 if (backupAgent != null) {
3384 ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
Kenny Rootd2d29252011-08-08 11:27:57 -07003385 if (DEBUG_BACKUP) {
3386 Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003387 + " from " + pkgName + "+" + backupAgent);
3388 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003389
3390 if (sa.getBoolean(
3391 com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
3392 true)) {
3393 ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
3394 }
3395 if (sa.getBoolean(
Christopher Tate3dda5182010-02-24 16:06:18 -08003396 com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
3397 false)) {
3398 ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
3399 }
Christopher Tated1de2562014-06-17 17:12:35 -07003400 if (sa.getBoolean(
3401 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
3402 false)) {
3403 ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
3404 }
Christopher Tate43fbc5f2016-02-17 18:00:48 -08003405 if (sa.getBoolean(
3406 com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
3407 false)) {
3408 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
3409 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003410 }
Matthew Williams303650c2015-04-17 18:22:51 -07003411
3412 TypedValue v = sa.peekValue(
3413 com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
3414 if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
3415 if (DEBUG_BACKUP) {
3416 Slog.v(TAG, "fullBackupContent specified as boolean=" +
3417 (v.data == 0 ? "false" : "true"));
3418 }
3419 // "false" => -1, "true" => 0
3420 ai.fullBackupContent = (v.data == 0 ? -1 : 0);
3421 }
3422 if (DEBUG_BACKUP) {
3423 Slog.v(TAG, "fullBackupContent=" + ai.fullBackupContent + " for " + pkgName);
3424 }
Christopher Tate181fafa2009-05-14 11:12:14 -07003425 }
Christopher Tate4a627c72011-04-01 14:43:32 -07003426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003427 ai.theme = sa.getResourceId(
Dianne Hackbornb35cd542011-01-04 21:30:53 -08003428 com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003429 ai.descriptionRes = sa.getResourceId(
3430 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
3431
Todd Kennedy232d29e2017-11-06 14:45:53 -08003432 if (sa.getBoolean(
3433 com.android.internal.R.styleable.AndroidManifestApplication_persistent,
3434 false)) {
3435 // Check if persistence is based on a feature being present
3436 final String requiredFeature = sa.getNonResourceString(com.android.internal.R.styleable
3437 .AndroidManifestApplication_persistentWhenFeatureAvailable);
3438 if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
3439 ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440 }
Amith Yamasani0d8750d2013-05-01 15:25:28 -07003441 }
3442
3443 if (sa.getBoolean(
3444 com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
3445 false)) {
3446 owner.mRequiredForAllUsers = true;
Amith Yamasanie993ae12013-04-15 13:42:57 -07003447 }
3448
3449 String restrictedAccountType = sa.getString(com.android.internal.R.styleable
3450 .AndroidManifestApplication_restrictedAccountType);
3451 if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
3452 owner.mRestrictedAccountType = restrictedAccountType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003453 }
3454
Amith Yamasaniccbe3892013-04-12 17:52:42 -07003455 String requiredAccountType = sa.getString(com.android.internal.R.styleable
3456 .AndroidManifestApplication_requiredAccountType);
3457 if (requiredAccountType != null && requiredAccountType.length() > 0) {
3458 owner.mRequiredAccountType = requiredAccountType;
3459 }
3460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003461 if (sa.getBoolean(
3462 com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
3463 false)) {
3464 ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
3465 }
3466
3467 if (sa.getBoolean(
Ben Chengef3f5dd2010-03-29 15:47:26 -07003468 com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
Ben Cheng23085b72010-02-08 16:06:32 -08003469 false)) {
3470 ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
3471 }
3472
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003473 owner.baseHardwareAccelerated = sa.getBoolean(
Romain Guy812ccbe2010-06-01 14:07:24 -07003474 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
Dianne Hackborn2d6833b2011-06-24 16:04:19 -07003475 owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
Alan Viveretted70b9e72015-05-27 14:29:20 -07003476 if (owner.baseHardwareAccelerated) {
3477 ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
3478 }
Romain Guy812ccbe2010-06-01 14:07:24 -07003479
3480 if (sa.getBoolean(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003481 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
3482 true)) {
3483 ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
3484 }
3485
3486 if (sa.getBoolean(
3487 com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
3488 false)) {
3489 ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
3490 }
3491
3492 if (sa.getBoolean(
3493 com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
3494 true)) {
3495 ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
3496 }
3497
Svet Ganov354cd3c2015-12-17 11:35:04 -08003498 // The parent package controls installation, hence specify test only installs.
3499 if (owner.parentPackage == null) {
3500 if (sa.getBoolean(
3501 com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
3502 false)) {
3503 ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
3504 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003505 }
3506
Jason parksa3cdaa52011-01-13 14:15:43 -06003507 if (sa.getBoolean(
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003508 com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
Jason parksa3cdaa52011-01-13 14:15:43 -06003509 false)) {
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08003510 ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
Jason parksa3cdaa52011-01-13 14:15:43 -06003511 }
3512
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003513 if (sa.getBoolean(
Alex Klyubin01a959d2015-03-18 10:05:45 -07003514 com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
3515 true)) {
3516 ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
3517 }
3518
3519 if (sa.getBoolean(
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -07003520 com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
3521 false /* default is no RTL support*/)) {
3522 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
3523 }
3524
Narayan Kamath589a1bc2014-07-03 14:43:26 +01003525 if (sa.getBoolean(
3526 com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
3527 false)) {
3528 ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
3529 }
3530
Dmitriy Ivanovff193d62014-09-30 15:10:48 -07003531 if (sa.getBoolean(
3532 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
3533 true)) {
3534 ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
3535 }
3536
Todd Kennedyd022ac22016-04-13 10:49:29 -07003537 if (sa.getBoolean(
3538 R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
3539 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003540 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003541 }
Todd Kennedyd022ac22016-04-13 10:49:29 -07003542 if (sa.getBoolean(
3543 R.styleable.AndroidManifestApplication_directBootAware,
3544 false)) {
Jeff Sharkey8a372a02016-03-16 16:25:45 -06003545 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
Jeff Sharkeyf9fc6d62015-11-08 16:46:05 -08003546 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08003547
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003548 if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
3549 if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003550 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
3551 } else {
3552 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07003553 }
3554 } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
Wale Ogunwalee633eb02017-03-30 12:57:29 -07003555 ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Wale Ogunwale6afdf912016-01-30 13:01:33 -08003556 }
3557
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07003558 ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
3559
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003560 ai.networkSecurityConfigRes = sa.getResourceId(
3561 com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig,
3562 0);
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07003563 ai.category = sa.getInt(
3564 com.android.internal.R.styleable.AndroidManifestApplication_appCategory,
3565 ApplicationInfo.CATEGORY_UNDEFINED);
Chad Brubakerc845b2a2016-05-13 14:09:27 -07003566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003567 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003568 str = sa.getNonConfigurationString(
3569 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003570 ai.permission = (str != null && str.length() > 0) ? str.intern() : null;
3571
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003572 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3573 str = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003574 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
3575 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003576 } else {
3577 // Some older apps have been seen to use a resource reference
3578 // here that on older builds was ignored (with a warning). We
3579 // need to continue to do this for them so they don't break.
3580 str = sa.getNonResourceString(
3581 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
3582 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003583 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
3584 str, outError);
Jason Monka80bfb52017-11-16 17:15:37 -05003585 String factory = sa.getNonResourceString(
3586 com.android.internal.R.styleable.AndroidManifestApplication_appComponentFactory);
3587 if (factory != null) {
3588 ai.appComponentFactory = buildClassName(ai.packageName, factory, outError);
3589 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003590
3591 if (outError[0] == null) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003592 CharSequence pname;
3593 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3594 pname = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07003595 com.android.internal.R.styleable.AndroidManifestApplication_process,
3596 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07003597 } else {
3598 // Some older apps have been seen to use a resource reference
3599 // here that on older builds was ignored (with a warning). We
3600 // need to continue to do this for them so they don't break.
3601 pname = sa.getNonResourceString(
3602 com.android.internal.R.styleable.AndroidManifestApplication_process);
3603 }
3604 ai.processName = buildProcessName(ai.packageName, null, pname,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003605 flags, mSeparateProcesses, outError);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003606
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003607 ai.enabled = sa.getBoolean(
3608 com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07003609
Jose Lima12d0b4c2014-03-14 16:55:12 -07003610 if (sa.getBoolean(
3611 com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
3612 ai.flags |= ApplicationInfo.FLAG_IS_GAME;
3613 }
3614
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003615 if (sa.getBoolean(
3616 com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
3617 false)) {
3618 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
Dianne Hackborn02486b12010-08-26 14:18:37 -07003619
Dianne Hackborn70c95c52017-10-06 16:30:59 -07003620 // A heavy-weight application can not be in a custom process.
3621 // We can do direct compare because we intern all strings.
3622 if (ai.processName != null && !ai.processName.equals(ai.packageName)) {
3623 outError[0] = "cantSaveState applications can not use custom processes";
Dianne Hackborn860755f2010-06-03 18:47:52 -07003624 }
3625 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003626 }
3627
Adam Powell269248d2011-08-02 10:26:54 -07003628 ai.uiOptions = sa.getInt(
3629 com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
3630
Narayan Kamath96c11c52017-08-09 13:07:21 +01003631 ai.classLoaderName = sa.getString(
3632 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
3633 if (ai.classLoaderName != null
3634 && !ClassLoaderFactory.isValidClassLoaderName(ai.classLoaderName)) {
3635 outError[0] = "Invalid class loader name: " + ai.classLoaderName;
3636 }
3637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003638 sa.recycle();
3639
3640 if (outError[0] != null) {
3641 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3642 return false;
3643 }
3644
3645 final int innerDepth = parser.getDepth();
Garrett Boyer52136662017-05-23 13:47:58 -07003646 // IMPORTANT: These must only be cached for a single <application> to avoid components
3647 // getting added to the wrong package.
3648 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003649 int type;
Bryce Lee22571db2017-07-07 15:54:18 -07003650
Kenny Rootd2d29252011-08-08 11:27:57 -07003651 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3652 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3653 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003654 continue;
3655 }
3656
3657 String tagName = parser.getName();
3658 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003659 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003660 owner.baseHardwareAccelerated);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003661 if (a == null) {
3662 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3663 return false;
3664 }
3665
3666 owner.activities.add(a);
3667
3668 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003669 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
3670 true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003671 if (a == null) {
3672 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3673 return false;
3674 }
3675
3676 owner.receivers.add(a);
3677
3678 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003679 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003680 if (s == null) {
3681 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3682 return false;
3683 }
3684
3685 owner.services.add(s);
3686
3687 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003688 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003689 if (p == null) {
3690 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3691 return false;
3692 }
3693
3694 owner.providers.add(p);
3695
3696 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003697 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003698 if (a == null) {
3699 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3700 return false;
3701 }
3702
3703 owner.activities.add(a);
3704
3705 } else if (parser.getName().equals("meta-data")) {
3706 // note: application meta-data is stored off to the side, so it can
3707 // remain null in the primary copy (we like to avoid extra copies because
3708 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003709 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003710 outError)) == null) {
3711 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3712 return false;
3713 }
Svet Ganov67882122016-12-11 16:36:34 -08003714 } else if (tagName.equals("static-library")) {
3715 sa = res.obtainAttributes(parser,
3716 com.android.internal.R.styleable.AndroidManifestStaticLibrary);
3717
3718 // Note: don't allow this value to be a reference to a resource
3719 // that may change.
3720 final String lname = sa.getNonResourceString(
3721 com.android.internal.R.styleable.AndroidManifestStaticLibrary_name);
3722 final int version = sa.getInt(
3723 com.android.internal.R.styleable.AndroidManifestStaticLibrary_version, -1);
Dianne Hackborn3accca02013-09-20 09:32:11 -07003724 final int versionMajor = sa.getInt(
3725 com.android.internal.R.styleable.AndroidManifestStaticLibrary_versionMajor,
3726 0);
Svet Ganov67882122016-12-11 16:36:34 -08003727
3728 sa.recycle();
3729
3730 // Since the app canot run without a static lib - fail if malformed
3731 if (lname == null || version < 0) {
3732 outError[0] = "Bad static-library declaration name: " + lname
3733 + " version: " + version;
3734 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3735 XmlUtils.skipCurrentTag(parser);
3736 return false;
3737 }
3738
3739 if (owner.mSharedUserId != null) {
3740 outError[0] = "sharedUserId not allowed in static shared library";
3741 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
3742 XmlUtils.skipCurrentTag(parser);
3743 return false;
3744 }
3745
3746 if (owner.staticSharedLibName != null) {
3747 outError[0] = "Multiple static-shared libs for package " + pkgName;
3748 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3749 XmlUtils.skipCurrentTag(parser);
3750 return false;
3751 }
3752
3753 owner.staticSharedLibName = lname.intern();
Dianne Hackborn3accca02013-09-20 09:32:11 -07003754 if (version >= 0) {
3755 owner.staticSharedLibVersion =
3756 PackageInfo.composeLongVersionCode(versionMajor, version);
3757 } else {
3758 owner.staticSharedLibVersion = version;
3759 }
Svet Ganov67882122016-12-11 16:36:34 -08003760 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY;
3761
3762 XmlUtils.skipCurrentTag(parser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003763
Dianne Hackbornc895be72013-03-11 17:48:43 -07003764 } else if (tagName.equals("library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003765 sa = res.obtainAttributes(parser,
Dianne Hackbornc895be72013-03-11 17:48:43 -07003766 com.android.internal.R.styleable.AndroidManifestLibrary);
3767
3768 // Note: don't allow this value to be a reference to a resource
3769 // that may change.
3770 String lname = sa.getNonResourceString(
3771 com.android.internal.R.styleable.AndroidManifestLibrary_name);
3772
3773 sa.recycle();
3774
3775 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003776 lname = lname.intern();
3777 if (!ArrayUtils.contains(owner.libraryNames, lname)) {
Svet Ganov67882122016-12-11 16:36:34 -08003778 owner.libraryNames = ArrayUtils.add(
3779 owner.libraryNames, lname);
Dianne Hackbornc895be72013-03-11 17:48:43 -07003780 }
3781 }
3782
3783 XmlUtils.skipCurrentTag(parser);
3784
Svet Ganov67882122016-12-11 16:36:34 -08003785 } else if (tagName.equals("uses-static-library")) {
3786 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
3787 return false;
3788 }
3789
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003790 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003791 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003792 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3793
Dianne Hackborncf244ad2010-03-09 15:00:30 -08003794 // Note: don't allow this value to be a reference to a resource
3795 // that may change.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003796 String lname = sa.getNonResourceString(
3797 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
Dianne Hackborn49237342009-08-27 20:08:01 -07003798 boolean req = sa.getBoolean(
3799 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3800 true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003801
3802 sa.recycle();
3803
Dianne Hackborn49237342009-08-27 20:08:01 -07003804 if (lname != null) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003805 lname = lname.intern();
Dianne Hackborn49237342009-08-27 20:08:01 -07003806 if (req) {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003807 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07003808 } else {
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003809 owner.usesOptionalLibraries = ArrayUtils.add(
3810 owner.usesOptionalLibraries, lname);
3811 }
3812 }
3813
3814 XmlUtils.skipCurrentTag(parser);
3815
3816 } else if (tagName.equals("uses-package")) {
3817 // Dependencies for app installers; we don't currently try to
3818 // enforce this.
3819 XmlUtils.skipCurrentTag(parser);
3820
3821 } else {
3822 if (!RIGID_PARSER) {
3823 Slog.w(TAG, "Unknown element under <application>: " + tagName
3824 + " at " + mArchiveSourcePath + " "
3825 + parser.getPositionDescription());
3826 XmlUtils.skipCurrentTag(parser);
3827 continue;
3828 } else {
3829 outError[0] = "Bad element under <application>: " + tagName;
3830 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3831 return false;
3832 }
3833 }
3834 }
3835
Bryce Lee22571db2017-07-07 15:54:18 -07003836 // Must be ran after the entire {@link ApplicationInfo} has been fully processed and after
3837 // every activity info has had a chance to set it from its attributes.
3838 setMaxAspectRatio(owner);
3839
Paul Duffin855d7022017-07-10 15:16:07 +01003840 PackageBackwardCompatibility.modifySharedLibraries(owner);
Narayan Kamathe2d2ed42015-01-13 15:51:57 +00003841
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003842 if (hasDomainURLs(owner)) {
3843 owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3844 } else {
3845 owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
3846 }
3847
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003848 return true;
3849 }
3850
3851 /**
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003852 * 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 -07003853 */
3854 private static boolean hasDomainURLs(Package pkg) {
3855 if (pkg == null || pkg.activities == null) return false;
3856 final ArrayList<Activity> activities = pkg.activities;
3857 final int countActivities = activities.size();
3858 for (int n=0; n<countActivities; n++) {
3859 Activity activity = activities.get(n);
3860 ArrayList<ActivityIntentInfo> filters = activity.intents;
3861 if (filters == null) continue;
3862 final int countFilters = filters.size();
3863 for (int m=0; m<countFilters; m++) {
3864 ActivityIntentInfo aii = filters.get(m);
3865 if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
Fabrice Di Meglioe48c1372015-04-09 15:55:42 -07003866 if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
Fabrice Di Megliod3d8a322015-04-01 15:58:47 -07003867 if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
3868 aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
3869 return true;
3870 }
3871 }
3872 }
3873 return false;
3874 }
3875
3876 /**
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003877 * Parse the {@code application} XML tree at the current parse location in a
3878 * <em>split APK</em> manifest.
3879 * <p>
3880 * Note that split APKs have many more restrictions on what they're capable
3881 * of doing, so many valid features of a base APK have been carefully
3882 * omitted here.
3883 */
Svet Ganov354cd3c2015-12-17 11:35:04 -08003884 private boolean parseSplitApplication(Package owner, Resources res, XmlResourceParser parser,
3885 int flags, int splitIndex, String[] outError)
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003886 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003887 TypedArray sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003888 com.android.internal.R.styleable.AndroidManifestApplication);
3889
3890 if (sa.getBoolean(
3891 com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
3892 owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
3893 }
3894
Narayan Kamath96c11c52017-08-09 13:07:21 +01003895 final String classLoaderName = sa.getString(
3896 com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
3897 if (classLoaderName == null || ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) {
3898 owner.applicationInfo.splitClassLoaderNames[splitIndex] = classLoaderName;
3899 } else {
3900 outError[0] = "Invalid class loader name: " + classLoaderName;
3901 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3902 return false;
3903 }
3904
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003905 final int innerDepth = parser.getDepth();
3906 int type;
3907 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
3908 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
3909 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
3910 continue;
3911 }
3912
Adam Lesinski4e862812016-11-21 16:02:24 -08003913 ComponentInfo parsedComponent = null;
3914
Garrett Boyer52136662017-05-23 13:47:58 -07003915 // IMPORTANT: These must only be cached for a single <application> to avoid components
3916 // getting added to the wrong package.
3917 final CachedComponentArgs cachedArgs = new CachedComponentArgs();
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003918 String tagName = parser.getName();
3919 if (tagName.equals("activity")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003920 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003921 owner.baseHardwareAccelerated);
3922 if (a == null) {
3923 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3924 return false;
3925 }
3926
3927 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003928 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003929
3930 } else if (tagName.equals("receiver")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003931 Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
3932 true, false);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003933 if (a == null) {
3934 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3935 return false;
3936 }
3937
3938 owner.receivers.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003939 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003940
3941 } else if (tagName.equals("service")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003942 Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003943 if (s == null) {
3944 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3945 return false;
3946 }
3947
3948 owner.services.add(s);
Adam Lesinski4e862812016-11-21 16:02:24 -08003949 parsedComponent = s.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003950
3951 } else if (tagName.equals("provider")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003952 Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003953 if (p == null) {
3954 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3955 return false;
3956 }
3957
3958 owner.providers.add(p);
Adam Lesinski4e862812016-11-21 16:02:24 -08003959 parsedComponent = p.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003960
3961 } else if (tagName.equals("activity-alias")) {
Garrett Boyer52136662017-05-23 13:47:58 -07003962 Activity a = parseActivityAlias(owner, res, parser, flags, outError, cachedArgs);
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003963 if (a == null) {
3964 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3965 return false;
3966 }
3967
3968 owner.activities.add(a);
Adam Lesinski4e862812016-11-21 16:02:24 -08003969 parsedComponent = a.info;
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003970
3971 } else if (parser.getName().equals("meta-data")) {
3972 // note: application meta-data is stored off to the side, so it can
3973 // remain null in the primary copy (we like to avoid extra copies because
3974 // it can be large)
Svet Ganov354cd3c2015-12-17 11:35:04 -08003975 if ((owner.mAppMetaData = parseMetaData(res, parser, owner.mAppMetaData,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003976 outError)) == null) {
3977 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
3978 return false;
3979 }
3980
Svet Ganov67882122016-12-11 16:36:34 -08003981 } else if (tagName.equals("uses-static-library")) {
3982 if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
3983 return false;
3984 }
3985
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003986 } else if (tagName.equals("uses-library")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08003987 sa = res.obtainAttributes(parser,
Jeff Sharkeyda96e132014-07-15 14:54:09 -07003988 com.android.internal.R.styleable.AndroidManifestUsesLibrary);
3989
3990 // Note: don't allow this value to be a reference to a resource
3991 // that may change.
3992 String lname = sa.getNonResourceString(
3993 com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
3994 boolean req = sa.getBoolean(
3995 com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
3996 true);
3997
3998 sa.recycle();
3999
4000 if (lname != null) {
4001 lname = lname.intern();
4002 if (req) {
4003 // Upgrade to treat as stronger constraint
4004 owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
4005 owner.usesOptionalLibraries = ArrayUtils.remove(
4006 owner.usesOptionalLibraries, lname);
4007 } else {
4008 // Ignore if someone already defined as required
4009 if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
4010 owner.usesOptionalLibraries = ArrayUtils.add(
4011 owner.usesOptionalLibraries, lname);
Dianne Hackborn49237342009-08-27 20:08:01 -07004012 }
4013 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004014 }
4015
4016 XmlUtils.skipCurrentTag(parser);
4017
Dianne Hackborncef65ee2010-09-30 18:27:22 -07004018 } else if (tagName.equals("uses-package")) {
4019 // Dependencies for app installers; we don't currently try to
4020 // enforce this.
4021 XmlUtils.skipCurrentTag(parser);
4022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004023 } else {
4024 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004025 Slog.w(TAG, "Unknown element under <application>: " + tagName
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004026 + " at " + mArchiveSourcePath + " "
4027 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004028 XmlUtils.skipCurrentTag(parser);
4029 continue;
4030 } else {
4031 outError[0] = "Bad element under <application>: " + tagName;
4032 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
4033 return false;
4034 }
4035 }
Adam Lesinski4e862812016-11-21 16:02:24 -08004036
4037 if (parsedComponent != null && parsedComponent.splitName == null) {
4038 // If the loaded component did not specify a split, inherit the split name
4039 // based on the split it is defined in.
4040 // This is used to later load the correct split when starting this
4041 // component.
4042 parsedComponent.splitName = owner.splitNames[splitIndex];
4043 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004044 }
4045
4046 return true;
4047 }
4048
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004049 private static boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
4050 String[] outError, String tag, TypedArray sa, boolean nameRequired,
4051 int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00004052 // This case can only happen in unit tests where we sometimes need to create fakes
4053 // of various package parser data structures.
4054 if (sa == null) {
4055 outError[0] = tag + " does not contain any attributes";
4056 return false;
4057 }
4058
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004059 String name = sa.getNonConfigurationString(nameRes, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004060 if (name == null) {
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004061 if (nameRequired) {
4062 outError[0] = tag + " does not specify android:name";
4063 return false;
4064 }
4065 } else {
4066 outInfo.name
4067 = buildClassName(owner.applicationInfo.packageName, name, outError);
4068 if (outInfo.name == null) {
4069 return false;
4070 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004071 }
4072
Todd Kennedya83bfca2016-06-03 07:52:17 -07004073 final boolean useRoundIcon =
4074 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
4075 int roundIconVal = useRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004076 if (roundIconVal != 0) {
4077 outInfo.icon = roundIconVal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004078 outInfo.nonLocalizedLabel = null;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004079 } else {
4080 int iconVal = sa.getResourceId(iconRes, 0);
4081 if (iconVal != 0) {
4082 outInfo.icon = iconVal;
4083 outInfo.nonLocalizedLabel = null;
4084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004085 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004086
Adam Powell81cd2e92010-04-21 16:35:18 -07004087 int logoVal = sa.getResourceId(logoRes, 0);
4088 if (logoVal != 0) {
4089 outInfo.logo = logoVal;
4090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004091
Jose Limaf78e3122014-03-06 12:13:15 -08004092 int bannerVal = sa.getResourceId(bannerRes, 0);
4093 if (bannerVal != 0) {
4094 outInfo.banner = bannerVal;
4095 }
4096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 TypedValue v = sa.peekValue(labelRes);
4098 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
4099 outInfo.nonLocalizedLabel = v.coerceToString();
4100 }
4101
4102 outInfo.packageName = owner.packageName;
4103
4104 return true;
4105 }
4106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004107 private Activity parseActivity(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004108 XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs,
Romain Guy529b60a2010-08-03 18:05:47 -07004109 boolean receiver, boolean hardwareAccelerated)
4110 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004111 TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004112
Garrett Boyer52136662017-05-23 13:47:58 -07004113 if (cachedArgs.mActivityArgs == null) {
4114 cachedArgs.mActivityArgs = new ParseComponentArgs(owner, outError,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004115 R.styleable.AndroidManifestActivity_name,
4116 R.styleable.AndroidManifestActivity_label,
4117 R.styleable.AndroidManifestActivity_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004118 R.styleable.AndroidManifestActivity_roundIcon,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004119 R.styleable.AndroidManifestActivity_logo,
4120 R.styleable.AndroidManifestActivity_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004121 mSeparateProcesses,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004122 R.styleable.AndroidManifestActivity_process,
4123 R.styleable.AndroidManifestActivity_description,
4124 R.styleable.AndroidManifestActivity_enabled);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004125 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004126
Garrett Boyer52136662017-05-23 13:47:58 -07004127 cachedArgs.mActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
4128 cachedArgs.mActivityArgs.sa = sa;
4129 cachedArgs.mActivityArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004130
Garrett Boyer52136662017-05-23 13:47:58 -07004131 Activity a = new Activity(cachedArgs.mActivityArgs, new ActivityInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004132 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004133 sa.recycle();
4134 return null;
4135 }
4136
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004137 boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004138 if (setExported) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004139 a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004140 }
4141
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004142 a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004143
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004144 a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
Adam Powell269248d2011-08-02 10:26:54 -07004145 a.info.applicationInfo.uiOptions);
4146
Adam Powelldd8fab22012-03-22 17:47:27 -07004147 String parentName = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004148 R.styleable.AndroidManifestActivity_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004149 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004150 if (parentName != null) {
4151 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4152 if (outError[0] == null) {
4153 a.info.parentActivityName = parentClassName;
4154 } else {
4155 Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
4156 parentName);
4157 outError[0] = null;
4158 }
4159 }
4160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004161 String str;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004162 str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004163 if (str == null) {
4164 a.info.permission = owner.applicationInfo.permission;
4165 } else {
4166 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4167 }
4168
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004169 str = sa.getNonConfigurationString(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004170 R.styleable.AndroidManifestActivity_taskAffinity,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004171 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004172 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
4173 owner.applicationInfo.taskAffinity, str, outError);
4174
Todd Kennedye9d0d272017-01-23 06:49:29 -08004175 a.info.splitName =
4176 sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_splitName, 0);
4177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004178 a.info.flags = 0;
4179 if (sa.getBoolean(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004180 R.styleable.AndroidManifestActivity_multiprocess, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004181 a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
4182 }
4183
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004184 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004185 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
4186 }
4187
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004188 if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004189 a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
4190 }
4191
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004192 if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004193 a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
4194 }
4195
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004196 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004197 a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
4198 }
4199
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004200 if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004201 a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
4202 }
4203
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004204 if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004205 a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
4206 }
4207
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004208 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004209 (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
4210 a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
4211 }
4212
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004213 if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
Dianne Hackbornffa42482009-09-23 22:20:11 -07004214 a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
4215 }
4216
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07004217 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
4218 || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
4219 a.info.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
Craig Mautner5962b122012-10-05 14:45:52 -07004220 }
4221
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004222 if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
Daniel Sandler613dde42010-06-21 13:46:39 -04004223 a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
4224 }
Craig Mautner5962b122012-10-05 14:45:52 -07004225
Fyodor Kupolov4f5de342015-08-25 10:08:45 -07004226 if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
4227 a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
Fyodor Kupolov703d1c42015-01-27 11:59:00 -08004228 }
4229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004230 if (!receiver) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004231 if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
Romain Guy529b60a2010-08-03 18:05:47 -07004232 hardwareAccelerated)) {
4233 a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
4234 }
4235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004236 a.info.launchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004237 R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
Craig Mautner2dac0562014-05-06 09:06:44 -07004238 a.info.documentLaunchMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004239 R.styleable.AndroidManifestActivity_documentLaunchMode,
Craig Mautner2dac0562014-05-06 09:06:44 -07004240 ActivityInfo.DOCUMENT_LAUNCH_NONE);
Craig Mautnerffcfcaa2014-06-05 09:54:38 -07004241 a.info.maxRecents = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004242 R.styleable.AndroidManifestActivity_maxRecents,
Dianne Hackborn852975d2014-08-22 17:42:43 -07004243 ActivityManager.getDefaultAppRecentsLimitStatic());
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004244 a.info.configChanges = getActivityConfigChanges(
4245 sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004246 sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004247 a.info.softInputMode = sa.getInt(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004248 R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
Craig Mautner2dac0562014-05-06 09:06:44 -07004249
Craig Mautner43e52ed2014-06-16 17:18:52 -07004250 a.info.persistableMode = sa.getInteger(
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004251 R.styleable.AndroidManifestActivity_persistableMode,
Craig Mautner43e52ed2014-06-16 17:18:52 -07004252 ActivityInfo.PERSIST_ROOT_ONLY);
Craig Mautner2dac0562014-05-06 09:06:44 -07004253
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004254 if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004255 a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
4256 }
4257
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004258 if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
Craig Mautner2dac0562014-05-06 09:06:44 -07004259 a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
4260 }
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004261
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004262 if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07004263 a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
4264 }
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004265
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004266 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
Dianne Hackborna4e102e2014-09-04 22:52:27 -07004267 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
4268 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004269
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004270 a.info.screenOrientation = sa.getInt(
4271 R.styleable.AndroidManifestActivity_screenOrientation,
4272 SCREEN_ORIENTATION_UNSPECIFIED);
Wale Ogunwale6a591362015-10-05 20:18:27 -07004273
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004274 setActivityResizeMode(a.info, sa, owner);
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004275
Winson Chungd3395382016-12-13 11:49:09 -08004276 if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
4277 false)) {
4278 a.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE;
4279 }
4280
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004281 if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004282 a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
Wale Ogunwale6cae7652015-12-26 07:36:26 -08004283 }
Wale Ogunwaleb60692e2015-10-24 12:35:56 -07004284
Bryce Lee22571db2017-07-07 15:54:18 -07004285 if (sa.hasValue(R.styleable.AndroidManifestActivity_maxAspectRatio)
4286 && sa.getType(R.styleable.AndroidManifestActivity_maxAspectRatio)
4287 == TypedValue.TYPE_FLOAT) {
4288 a.setMaxAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_maxAspectRatio,
4289 0 /*default*/));
4290 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004291
Craig Mautner15df08a2015-04-01 12:17:18 -07004292 a.info.lockTaskLaunchMode =
4293 sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004294
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004295 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4296 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004297 false);
Ruben Brunkf56c9f42016-04-22 18:20:55 -07004298
4299 a.info.requestedVrComponent =
4300 sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
Robert Carr0f5d7532016-10-17 16:39:17 -07004301
4302 a.info.rotationAnimation =
Robert Carr427ba4f2017-07-17 18:37:06 -07004303 sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, ROTATION_ANIMATION_UNSPECIFIED);
Romain Guy48327452017-01-23 17:03:35 -08004304
4305 a.info.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode,
4306 ActivityInfo.COLOR_MODE_DEFAULT);
chaviw59b98852017-06-13 12:05:44 -07004307
4308 if (sa.getBoolean(R.styleable.AndroidManifestActivity_showWhenLocked, false)) {
4309 a.info.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
4310 }
4311
4312 if (sa.getBoolean(R.styleable.AndroidManifestActivity_turnScreenOn, false)) {
4313 a.info.flags |= ActivityInfo.FLAG_TURN_SCREEN_ON;
4314 }
4315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004316 } else {
4317 a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
4318 a.info.configChanges = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004319
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -08004320 if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07004321 a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004322 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004323
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004324 a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
4325 R.styleable.AndroidManifestActivity_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004326 false);
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004327 }
4328
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004329 if (a.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004330 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004331 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004332 }
4333
Todd Kennedy752fb702017-03-21 16:28:10 -07004334 // can't make this final; we may set it later via meta-data
4335 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08004336 sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004337 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004338 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004339 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004340 }
4341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004342 sa.recycle();
4343
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004344 if (receiver && (owner.applicationInfo.privateFlags
4345 &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004346 // A heavy-weight application can not have receives in its main process
4347 // We can do direct compare because we intern all strings.
4348 if (a.info.processName == owner.packageName) {
4349 outError[0] = "Heavy-weight applications can not have receivers in main process";
4350 }
4351 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004353 if (outError[0] != null) {
4354 return null;
4355 }
4356
4357 int outerDepth = parser.getDepth();
4358 int type;
4359 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4360 && (type != XmlPullParser.END_TAG
4361 || parser.getDepth() > outerDepth)) {
4362 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4363 continue;
4364 }
4365
4366 if (parser.getName().equals("intent-filter")) {
4367 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004368 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4369 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004370 return null;
4371 }
4372 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004373 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004374 + mArchiveSourcePath + " "
4375 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004376 } else {
4377 a.intents.add(intent);
4378 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004379 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004380 final int visibility = visibleToEphemeral
4381 ? IntentFilter.VISIBILITY_EXPLICIT
4382 : !receiver && isImplicitlyExposedIntent(intent)
4383 ? IntentFilter.VISIBILITY_IMPLICIT
4384 : IntentFilter.VISIBILITY_NONE;
4385 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004386 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004387 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4388 }
4389 if (intent.isImplicitlyVisibleToInstantApp()) {
4390 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004391 }
Jeff Sharkey32ee8ee2017-03-08 20:17:51 -07004392 if (LOG_UNSAFE_BROADCASTS && receiver
4393 && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
4394 for (int i = 0; i < intent.countActions(); i++) {
4395 final String action = intent.getAction(i);
4396 if (action == null || !action.startsWith("android.")) continue;
4397 if (!SAFE_BROADCASTS.contains(action)) {
4398 Slog.w(TAG, "Broadcast " + action + " may never be delivered to "
4399 + owner.packageName + " as requested at: "
4400 + parser.getPositionDescription());
4401 }
4402 }
4403 }
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004404 } else if (!receiver && parser.getName().equals("preferred")) {
4405 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004406 if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/,
4407 intent, outError)) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07004408 return null;
4409 }
4410 if (intent.countActions() == 0) {
4411 Slog.w(TAG, "No actions in preferred at "
4412 + mArchiveSourcePath + " "
4413 + parser.getPositionDescription());
4414 } else {
4415 if (owner.preferredActivityFilters == null) {
4416 owner.preferredActivityFilters = new ArrayList<ActivityIntentInfo>();
4417 }
4418 owner.preferredActivityFilters.add(intent);
4419 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004420 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004421 final int visibility = visibleToEphemeral
4422 ? IntentFilter.VISIBILITY_EXPLICIT
4423 : !receiver && isImplicitlyExposedIntent(intent)
4424 ? IntentFilter.VISIBILITY_IMPLICIT
4425 : IntentFilter.VISIBILITY_NONE;
4426 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004427 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004428 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4429 }
4430 if (intent.isImplicitlyVisibleToInstantApp()) {
4431 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004433 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004434 if ((a.metaData = parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004435 outError)) == null) {
4436 return null;
4437 }
Todd Kennedy752fb702017-03-21 16:28:10 -07004438 // we don't have an attribute [or it's false], but, we have meta-data
4439 if (!visibleToEphemeral && a.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
4440 visibleToEphemeral = true; // set in case there are more intent filters
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004441 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4442 a.info.flags &= ~ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy752fb702017-03-21 16:28:10 -07004443 owner.visibleToInstantApps = true;
4444 // cycle through any filters already seen
4445 for (int i = a.intents.size() - 1; i >= 0; --i) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004446 a.intents.get(i)
4447 .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
Todd Kennedy752fb702017-03-21 16:28:10 -07004448 }
4449 if (owner.preferredActivityFilters != null) {
4450 for (int i = owner.preferredActivityFilters.size() - 1; i >= 0; --i) {
4451 owner.preferredActivityFilters.get(i)
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004452 .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
Todd Kennedy752fb702017-03-21 16:28:10 -07004453 }
4454 }
4455 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004456 } else if (!receiver && parser.getName().equals("layout")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004457 parseLayout(res, parser, a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004458 } else {
4459 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004460 Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004461 if (receiver) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004462 Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004463 + " at " + mArchiveSourcePath + " "
4464 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004465 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004466 Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004467 + " at " + mArchiveSourcePath + " "
4468 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004469 }
4470 XmlUtils.skipCurrentTag(parser);
4471 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004472 } else {
Kenny Rootd2d29252011-08-08 11:27:57 -07004473 if (receiver) {
4474 outError[0] = "Bad element under <receiver>: " + parser.getName();
4475 } else {
4476 outError[0] = "Bad element under <activity>: " + parser.getName();
4477 }
4478 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004479 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004480 }
4481 }
4482
4483 if (!setExported) {
4484 a.info.exported = a.intents.size() > 0;
4485 }
4486
4487 return a;
4488 }
4489
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004490 private void setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package owner) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004491 final boolean appExplicitDefault = (owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004492 & (PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE
4493 | PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE)) != 0;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004494
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004495 if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity)
4496 || appExplicitDefault) {
4497 // Activity or app explicitly set if it is resizeable or not;
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004498 final boolean appResizeable = (owner.applicationInfo.privateFlags
4499 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE) != 0;
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004500 if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity,
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004501 appResizeable)) {
Winson Chungd3395382016-12-13 11:49:09 -08004502 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004503 } else {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004504 aInfo.resizeMode = RESIZE_MODE_UNRESIZEABLE;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004505 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004506 return;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004507 }
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004508
4509 if ((owner.applicationInfo.privateFlags
Wale Ogunwalee633eb02017-03-30 12:57:29 -07004510 & PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) != 0) {
Wale Ogunwale72a73e32016-10-13 12:16:39 -07004511 // The activity or app didn't explicitly set the resizing option, however we want to
4512 // make it resize due to the sdk version it is targeting.
4513 aInfo.resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
4514 return;
4515 }
4516
4517 // resize preference isn't set and target sdk version doesn't support resizing apps by
4518 // default. For the app to be resizeable if it isn't fixed orientation or immersive.
skuhne@google.com322347b2016-12-02 12:54:03 -08004519 if (aInfo.isFixedOrientationPortrait()) {
4520 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
4521 } else if (aInfo.isFixedOrientationLandscape()) {
4522 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
4523 } else if (aInfo.isFixedOrientation()) {
4524 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
4525 } else {
4526 aInfo.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
4527 }
Wale Ogunwale3eadad72016-10-13 09:16:59 -07004528 }
4529
Bryce Lee22571db2017-07-07 15:54:18 -07004530 /**
4531 * Sets every the max aspect ratio of every child activity that doesn't already have an aspect
4532 * ratio set.
4533 */
4534 private void setMaxAspectRatio(Package owner) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004535 // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater.
4536 // 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 -07004537 float maxAspectRatio = owner.applicationInfo.targetSdkVersion < O
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004538 ? DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0;
Bryce Lee22571db2017-07-07 15:54:18 -07004539
4540 if (owner.applicationInfo.maxAspectRatio != 0) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004541 // Use the application max aspect ration as default if set.
Bryce Lee22571db2017-07-07 15:54:18 -07004542 maxAspectRatio = owner.applicationInfo.maxAspectRatio;
4543 } else if (owner.mAppMetaData != null
4544 && owner.mAppMetaData.containsKey(METADATA_MAX_ASPECT_RATIO)) {
4545 maxAspectRatio = owner.mAppMetaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004546 }
4547
Bryce Lee22571db2017-07-07 15:54:18 -07004548 for (Activity activity : owner.activities) {
4549 // If the max aspect ratio for the activity has already been set, skip.
4550 if (activity.hasMaxAspectRatio()) {
4551 continue;
4552 }
4553
4554 // By default we prefer to use a values defined on the activity directly than values
4555 // defined on the application. We do not check the styled attributes on the activity
4556 // as it would have already been set when we processed the activity. We wait to process
4557 // the meta data here since this method is called at the end of processing the
4558 // application and all meta data is guaranteed.
4559 final float activityAspectRatio = activity.metaData != null
4560 ? activity.metaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio)
4561 : maxAspectRatio;
4562
4563 activity.setMaxAspectRatio(activityAspectRatio);
Wale Ogunwale0cb70ac2017-03-27 09:16:38 -07004564 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004565 }
4566
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004567 /**
4568 * @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml.
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004569 * @param recreateOnConfigChanges The bit mask recreateOnConfigChanges fetched from
4570 * AndroidManifest.xml.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004571 * @hide Exposed for unit testing only.
4572 */
4573 @TestApi
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -07004574 public static int getActivityConfigChanges(int configChanges, int recreateOnConfigChanges) {
4575 return configChanges | ((~recreateOnConfigChanges) & RECREATE_ON_CONFIG_CHANGES_MASK);
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -08004576 }
4577
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004578 private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004579 TypedArray sw = res.obtainAttributes(attrs,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004580 com.android.internal.R.styleable.AndroidManifestLayout);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004581 int width = -1;
4582 float widthFraction = -1f;
4583 int height = -1;
4584 float heightFraction = -1f;
4585 final int widthType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004586 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004587 if (widthType == TypedValue.TYPE_FRACTION) {
4588 widthFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004589 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004590 1, 1, -1);
4591 } else if (widthType == TypedValue.TYPE_DIMENSION) {
4592 width = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004593 com.android.internal.R.styleable.AndroidManifestLayout_defaultWidth,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004594 -1);
4595 }
4596 final int heightType = sw.getType(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004597 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004598 if (heightType == TypedValue.TYPE_FRACTION) {
4599 heightFraction = sw.getFraction(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004600 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004601 1, 1, -1);
4602 } else if (heightType == TypedValue.TYPE_DIMENSION) {
4603 height = sw.getDimensionPixelSize(
Wale Ogunwaleb12e1092016-01-30 12:23:09 -08004604 com.android.internal.R.styleable.AndroidManifestLayout_defaultHeight,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004605 -1);
4606 }
4607 int gravity = sw.getInt(
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004608 com.android.internal.R.styleable.AndroidManifestLayout_gravity,
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004609 Gravity.CENTER);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004610 int minWidth = sw.getDimensionPixelSize(
4611 com.android.internal.R.styleable.AndroidManifestLayout_minWidth,
Andrii Kulian2e751b82016-03-16 16:59:32 -07004612 -1);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004613 int minHeight = sw.getDimensionPixelSize(
4614 com.android.internal.R.styleable.AndroidManifestLayout_minHeight,
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004615 -1);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004616 sw.recycle();
Andrii Kulian2e751b82016-03-16 16:59:32 -07004617 a.info.windowLayout = new ActivityInfo.WindowLayout(width, widthFraction,
Andrii Kulianf66a83d2016-05-17 12:17:44 -07004618 height, heightFraction, gravity, minWidth, minHeight);
Filip Gruszczynski848fe6b2015-08-19 13:32:41 -07004619 }
4620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004621 private Activity parseActivityAlias(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004622 XmlResourceParser parser, int flags, String[] outError,
4623 CachedComponentArgs cachedArgs)
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004624 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004625 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004626 com.android.internal.R.styleable.AndroidManifestActivityAlias);
4627
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004628 String targetActivity = sa.getNonConfigurationString(
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004629 com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity,
4630 Configuration.NATIVE_CONFIG_VERSION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004631 if (targetActivity == null) {
4632 outError[0] = "<activity-alias> does not specify android:targetActivity";
4633 sa.recycle();
4634 return null;
4635 }
4636
4637 targetActivity = buildClassName(owner.applicationInfo.packageName,
4638 targetActivity, outError);
4639 if (targetActivity == null) {
4640 sa.recycle();
4641 return null;
4642 }
4643
Garrett Boyer52136662017-05-23 13:47:58 -07004644 if (cachedArgs.mActivityAliasArgs == null) {
4645 cachedArgs.mActivityAliasArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004646 com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
4647 com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
4648 com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004649 com.android.internal.R.styleable.AndroidManifestActivityAlias_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004650 com.android.internal.R.styleable.AndroidManifestActivityAlias_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004651 com.android.internal.R.styleable.AndroidManifestActivityAlias_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004652 mSeparateProcesses,
4653 0,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004654 com.android.internal.R.styleable.AndroidManifestActivityAlias_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004655 com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07004656 cachedArgs.mActivityAliasArgs.tag = "<activity-alias>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004657 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004658
Garrett Boyer52136662017-05-23 13:47:58 -07004659 cachedArgs.mActivityAliasArgs.sa = sa;
4660 cachedArgs.mActivityAliasArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004662 Activity target = null;
4663
4664 final int NA = owner.activities.size();
4665 for (int i=0; i<NA; i++) {
4666 Activity t = owner.activities.get(i);
4667 if (targetActivity.equals(t.info.name)) {
4668 target = t;
4669 break;
4670 }
4671 }
4672
4673 if (target == null) {
4674 outError[0] = "<activity-alias> target activity " + targetActivity
4675 + " not found in manifest";
4676 sa.recycle();
4677 return null;
4678 }
4679
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004680 ActivityInfo info = new ActivityInfo();
4681 info.targetActivity = targetActivity;
4682 info.configChanges = target.info.configChanges;
4683 info.flags = target.info.flags;
4684 info.icon = target.info.icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07004685 info.logo = target.info.logo;
Jose Limaf78e3122014-03-06 12:13:15 -08004686 info.banner = target.info.banner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004687 info.labelRes = target.info.labelRes;
4688 info.nonLocalizedLabel = target.info.nonLocalizedLabel;
4689 info.launchMode = target.info.launchMode;
Yao Chen597ad3f2015-06-09 16:00:14 -07004690 info.lockTaskLaunchMode = target.info.lockTaskLaunchMode;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004691 info.processName = target.info.processName;
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004692 if (info.descriptionRes == 0) {
4693 info.descriptionRes = target.info.descriptionRes;
4694 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004695 info.screenOrientation = target.info.screenOrientation;
4696 info.taskAffinity = target.info.taskAffinity;
4697 info.theme = target.info.theme;
Dianne Hackborn0836c7c2011-10-20 18:40:23 -07004698 info.softInputMode = target.info.softInputMode;
Adam Powell269248d2011-08-02 10:26:54 -07004699 info.uiOptions = target.info.uiOptions;
Adam Powelldd8fab22012-03-22 17:47:27 -07004700 info.parentActivityName = target.info.parentActivityName;
Craig Mautner8307ea72014-09-11 15:03:53 -07004701 info.maxRecents = target.info.maxRecents;
Andrii Kulian2e751b82016-03-16 16:59:32 -07004702 info.windowLayout = target.info.windowLayout;
Wale Ogunwaled26176f2016-01-25 20:04:04 -08004703 info.resizeMode = target.info.resizeMode;
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07004704 info.maxAspectRatio = target.info.maxAspectRatio;
Bryce Lee22571db2017-07-07 15:54:18 -07004705
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004706 info.encryptionAware = info.directBootAware = target.info.directBootAware;
Craig Mautner8307ea72014-09-11 15:03:53 -07004707
Garrett Boyer52136662017-05-23 13:47:58 -07004708 Activity a = new Activity(cachedArgs.mActivityAliasArgs, info);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004709 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004710 sa.recycle();
4711 return null;
4712 }
4713
4714 final boolean setExported = sa.hasValue(
4715 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported);
4716 if (setExported) {
4717 a.info.exported = sa.getBoolean(
4718 com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
4719 }
4720
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004721 String str;
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004722 str = sa.getNonConfigurationString(
4723 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004724 if (str != null) {
4725 a.info.permission = str.length() > 0 ? str.toString().intern() : null;
4726 }
4727
Adam Powelldd8fab22012-03-22 17:47:27 -07004728 String parentName = sa.getNonConfigurationString(
4729 com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07004730 Configuration.NATIVE_CONFIG_VERSION);
Adam Powelldd8fab22012-03-22 17:47:27 -07004731 if (parentName != null) {
4732 String parentClassName = buildClassName(a.info.packageName, parentName, outError);
4733 if (outError[0] == null) {
4734 a.info.parentActivityName = parentClassName;
4735 } else {
4736 Log.e(TAG, "Activity alias " + a.info.name +
4737 " specified invalid parentActivityName " + parentName);
4738 outError[0] = null;
4739 }
4740 }
4741
Chad Brubaker699c7712017-01-20 13:53:42 -08004742 // TODO add visibleToInstantApps attribute to activity alias
Todd Kennedybe0b8892017-02-15 14:13:52 -08004743 final boolean visibleToEphemeral =
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004744 ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004745
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004746 sa.recycle();
4747
4748 if (outError[0] != null) {
4749 return null;
4750 }
4751
4752 int outerDepth = parser.getDepth();
4753 int type;
4754 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4755 && (type != XmlPullParser.END_TAG
4756 || parser.getDepth() > outerDepth)) {
4757 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4758 continue;
4759 }
4760
4761 if (parser.getName().equals("intent-filter")) {
4762 ActivityIntentInfo intent = new ActivityIntentInfo(a);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004763 if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
4764 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004765 return null;
4766 }
4767 if (intent.countActions() == 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004768 Slog.w(TAG, "No actions in intent filter at "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -07004769 + mArchiveSourcePath + " "
4770 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004771 } else {
4772 a.intents.add(intent);
4773 }
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004774 // adjust activity flags when we implicitly expose it via a browsable filter
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004775 final int visibility = visibleToEphemeral
4776 ? IntentFilter.VISIBILITY_EXPLICIT
4777 : isImplicitlyExposedIntent(intent)
4778 ? IntentFilter.VISIBILITY_IMPLICIT
4779 : IntentFilter.VISIBILITY_NONE;
4780 intent.setVisibilityToInstantApp(visibility);
Todd Kennedybe0b8892017-02-15 14:13:52 -08004781 if (intent.isVisibleToInstantApp()) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004782 a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
4783 }
4784 if (intent.isImplicitlyVisibleToInstantApp()) {
4785 a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004787 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004788 if ((a.metaData=parseMetaData(res, parser, a.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004789 outError)) == null) {
4790 return null;
4791 }
4792 } else {
4793 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07004794 Slog.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004795 + " at " + mArchiveSourcePath + " "
4796 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004797 XmlUtils.skipCurrentTag(parser);
4798 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07004799 } else {
4800 outError[0] = "Bad element under <activity-alias>: " + parser.getName();
4801 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004802 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004803 }
4804 }
4805
4806 if (!setExported) {
4807 a.info.exported = a.intents.size() > 0;
4808 }
4809
4810 return a;
4811 }
4812
4813 private Provider parseProvider(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07004814 XmlResourceParser parser, int flags, String[] outError,
4815 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004816 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004817 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004818 com.android.internal.R.styleable.AndroidManifestProvider);
4819
Garrett Boyer52136662017-05-23 13:47:58 -07004820 if (cachedArgs.mProviderArgs == null) {
4821 cachedArgs.mProviderArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004822 com.android.internal.R.styleable.AndroidManifestProvider_name,
4823 com.android.internal.R.styleable.AndroidManifestProvider_label,
4824 com.android.internal.R.styleable.AndroidManifestProvider_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07004825 com.android.internal.R.styleable.AndroidManifestProvider_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07004826 com.android.internal.R.styleable.AndroidManifestProvider_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08004827 com.android.internal.R.styleable.AndroidManifestProvider_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004828 mSeparateProcesses,
4829 com.android.internal.R.styleable.AndroidManifestProvider_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08004830 com.android.internal.R.styleable.AndroidManifestProvider_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004831 com.android.internal.R.styleable.AndroidManifestProvider_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07004832 cachedArgs.mProviderArgs.tag = "<provider>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004833 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004834
Garrett Boyer52136662017-05-23 13:47:58 -07004835 cachedArgs.mProviderArgs.sa = sa;
4836 cachedArgs.mProviderArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004837
Garrett Boyer52136662017-05-23 13:47:58 -07004838 Provider p = new Provider(cachedArgs.mProviderArgs, new ProviderInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004839 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004840 sa.recycle();
4841 return null;
4842 }
4843
Nick Kralevichf097b162012-07-28 12:43:48 -07004844 boolean providerExportedDefault = false;
4845
4846 if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
4847 // For compatibility, applications targeting API level 16 or lower
4848 // should have their content providers exported by default, unless they
4849 // specify otherwise.
4850 providerExportedDefault = true;
4851 }
4852
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004853 p.info.exported = sa.getBoolean(
Nick Kralevichf097b162012-07-28 12:43:48 -07004854 com.android.internal.R.styleable.AndroidManifestProvider_exported,
4855 providerExportedDefault);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004856
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004857 String cpname = sa.getNonConfigurationString(
4858 com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004859
4860 p.info.isSyncable = sa.getBoolean(
4861 com.android.internal.R.styleable.AndroidManifestProvider_syncable,
4862 false);
4863
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004864 String permission = sa.getNonConfigurationString(
4865 com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
4866 String str = sa.getNonConfigurationString(
4867 com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004868 if (str == null) {
4869 str = permission;
4870 }
4871 if (str == null) {
4872 p.info.readPermission = owner.applicationInfo.permission;
4873 } else {
4874 p.info.readPermission =
4875 str.length() > 0 ? str.toString().intern() : null;
4876 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08004877 str = sa.getNonConfigurationString(
4878 com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004879 if (str == null) {
4880 str = permission;
4881 }
4882 if (str == null) {
4883 p.info.writePermission = owner.applicationInfo.permission;
4884 } else {
4885 p.info.writePermission =
4886 str.length() > 0 ? str.toString().intern() : null;
4887 }
4888
4889 p.info.grantUriPermissions = sa.getBoolean(
4890 com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
4891 false);
4892
4893 p.info.multiprocess = sa.getBoolean(
4894 com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
4895 false);
4896
4897 p.info.initOrder = sa.getInt(
4898 com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
4899 0);
4900
Todd Kennedye9d0d272017-01-23 06:49:29 -08004901 p.info.splitName =
4902 sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_splitName, 0);
4903
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004904 p.info.flags = 0;
4905
4906 if (sa.getBoolean(
4907 com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
4908 false)) {
4909 p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
Dianne Hackborn7d19e022012-08-07 19:12:33 -07004910 }
4911
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004912 p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
4913 R.styleable.AndroidManifestProvider_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07004914 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004915 if (p.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07004916 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06004917 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07004918 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08004919
Todd Kennedybe0b8892017-02-15 14:13:52 -08004920 final boolean visibleToEphemeral =
4921 sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004922 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004923 p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07004924 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004925 }
4926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004927 sa.recycle();
4928
Alex Klyubinb9f8a522015-02-03 11:12:59 -08004929 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
4930 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004931 // A heavy-weight application can not have providers in its main process
4932 // We can do direct compare because we intern all strings.
4933 if (p.info.processName == owner.packageName) {
4934 outError[0] = "Heavy-weight applications can not have providers in main process";
4935 return null;
4936 }
4937 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 if (cpname == null) {
Nick Kralevichf097b162012-07-28 12:43:48 -07004940 outError[0] = "<provider> does not include authorities attribute";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004941 return null;
4942 }
Dianne Hackborn1bc177c2014-12-03 10:20:30 -08004943 if (cpname.length() <= 0) {
4944 outError[0] = "<provider> has empty authorities attribute";
4945 return null;
4946 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004947 p.info.authority = cpname.intern();
4948
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004949 if (!parseProviderTags(
Todd Kennedy752fb702017-03-21 16:28:10 -07004950 res, parser, visibleToEphemeral, owner, p, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004951 return null;
4952 }
4953
4954 return p;
4955 }
4956
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004957 private boolean parseProviderTags(Resources res, XmlResourceParser parser,
Todd Kennedy752fb702017-03-21 16:28:10 -07004958 boolean visibleToEphemeral, Package owner, Provider outInfo, String[] outError)
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004959 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004960 int outerDepth = parser.getDepth();
4961 int type;
4962 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
4963 && (type != XmlPullParser.END_TAG
4964 || parser.getDepth() > outerDepth)) {
4965 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
4966 continue;
4967 }
4968
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004969 if (parser.getName().equals("intent-filter")) {
4970 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08004971 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
4972 intent, outError)) {
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004973 return false;
4974 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004975 if (visibleToEphemeral) {
4976 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
4977 outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08004978 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004979 outInfo.intents.add(intent);
Jeff Sharkey85f5f812013-10-07 10:16:12 -07004980
4981 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004982 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004983 outInfo.metaData, outError)) == null) {
4984 return false;
4985 }
Todd Kennedy752fb702017-03-21 16:28:10 -07004986 // we don't have an attribute [or it's false], but, we have meta-data
4987 if (!visibleToEphemeral && outInfo.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
4988 visibleToEphemeral = true; // set in case there are more intent filters
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004989 outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy752fb702017-03-21 16:28:10 -07004990 owner.visibleToInstantApps = true;
4991 // cycle through any filters already seen
4992 for (int i = outInfo.intents.size() - 1; i >= 0; --i) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07004993 outInfo.intents.get(i)
4994 .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
Todd Kennedy752fb702017-03-21 16:28:10 -07004995 }
4996 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07004997
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004998 } else if (parser.getName().equals("grant-uri-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08004999 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005000 com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
5001
5002 PatternMatcher pa = null;
5003
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005004 String str = sa.getNonConfigurationString(
5005 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005006 if (str != null) {
5007 pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
5008 }
5009
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005010 str = sa.getNonConfigurationString(
5011 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005012 if (str != null) {
5013 pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
5014 }
5015
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005016 str = sa.getNonConfigurationString(
5017 com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005018 if (str != null) {
5019 pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5020 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005022 sa.recycle();
5023
5024 if (pa != null) {
5025 if (outInfo.info.uriPermissionPatterns == null) {
5026 outInfo.info.uriPermissionPatterns = new PatternMatcher[1];
5027 outInfo.info.uriPermissionPatterns[0] = pa;
5028 } else {
5029 final int N = outInfo.info.uriPermissionPatterns.length;
5030 PatternMatcher[] newp = new PatternMatcher[N+1];
5031 System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N);
5032 newp[N] = pa;
5033 outInfo.info.uriPermissionPatterns = newp;
5034 }
5035 outInfo.info.grantUriPermissions = true;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005036 } else {
5037 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005038 Slog.w(TAG, "Unknown element under <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005039 + parser.getName() + " at " + mArchiveSourcePath + " "
5040 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005041 XmlUtils.skipCurrentTag(parser);
5042 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005043 } else {
5044 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5045 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005046 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005047 }
5048 XmlUtils.skipCurrentTag(parser);
5049
5050 } else if (parser.getName().equals("path-permission")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005051 TypedArray sa = res.obtainAttributes(parser,
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005052 com.android.internal.R.styleable.AndroidManifestPathPermission);
5053
5054 PathPermission pa = null;
5055
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005056 String permission = sa.getNonConfigurationString(
5057 com.android.internal.R.styleable.AndroidManifestPathPermission_permission, 0);
5058 String readPermission = sa.getNonConfigurationString(
5059 com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005060 if (readPermission == null) {
5061 readPermission = permission;
5062 }
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005063 String writePermission = sa.getNonConfigurationString(
5064 com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005065 if (writePermission == null) {
5066 writePermission = permission;
5067 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005068
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005069 boolean havePerm = false;
5070 if (readPermission != null) {
5071 readPermission = readPermission.intern();
5072 havePerm = true;
5073 }
5074 if (writePermission != null) {
Bjorn Bringerte04b1ad2010-02-09 13:56:08 +00005075 writePermission = writePermission.intern();
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005076 havePerm = true;
5077 }
5078
5079 if (!havePerm) {
5080 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005081 Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005082 + parser.getName() + " at " + mArchiveSourcePath + " "
5083 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005084 XmlUtils.skipCurrentTag(parser);
5085 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005086 } else {
5087 outError[0] = "No readPermission or writePermssion for <path-permission>";
5088 return false;
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005089 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005090 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005091
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005092 String path = sa.getNonConfigurationString(
5093 com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005094 if (path != null) {
5095 pa = new PathPermission(path,
5096 PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
5097 }
5098
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005099 path = sa.getNonConfigurationString(
5100 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005101 if (path != null) {
5102 pa = new PathPermission(path,
5103 PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
5104 }
5105
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005106 path = sa.getNonConfigurationString(
5107 com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern, 0);
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005108 if (path != null) {
5109 pa = new PathPermission(path,
5110 PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
5111 }
5112
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005113 path = sa.getNonConfigurationString(
5114 com.android.internal.R.styleable.AndroidManifestPathPermission_pathAdvancedPattern, 0);
5115 if (path != null) {
5116 pa = new PathPermission(path,
5117 PatternMatcher.PATTERN_ADVANCED_GLOB, readPermission, writePermission);
5118 }
5119
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005120 sa.recycle();
5121
5122 if (pa != null) {
5123 if (outInfo.info.pathPermissions == null) {
5124 outInfo.info.pathPermissions = new PathPermission[1];
5125 outInfo.info.pathPermissions[0] = pa;
5126 } else {
5127 final int N = outInfo.info.pathPermissions.length;
5128 PathPermission[] newp = new PathPermission[N+1];
5129 System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
5130 newp[N] = pa;
5131 outInfo.info.pathPermissions = newp;
5132 }
5133 } else {
5134 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005135 Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005136 + parser.getName() + " at " + mArchiveSourcePath + " "
5137 + parser.getPositionDescription());
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005138 XmlUtils.skipCurrentTag(parser);
5139 continue;
5140 }
5141 outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
5142 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005143 }
5144 XmlUtils.skipCurrentTag(parser);
5145
5146 } else {
5147 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005148 Slog.w(TAG, "Unknown element under <provider>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005149 + parser.getName() + " at " + mArchiveSourcePath + " "
5150 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005151 XmlUtils.skipCurrentTag(parser);
5152 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005153 } else {
5154 outError[0] = "Bad element under <provider>: " + parser.getName();
5155 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005156 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005157 }
5158 }
5159 return true;
5160 }
5161
5162 private Service parseService(Package owner, Resources res,
Garrett Boyer52136662017-05-23 13:47:58 -07005163 XmlResourceParser parser, int flags, String[] outError,
5164 CachedComponentArgs cachedArgs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005165 throws XmlPullParserException, IOException {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005166 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005167 com.android.internal.R.styleable.AndroidManifestService);
5168
Garrett Boyer52136662017-05-23 13:47:58 -07005169 if (cachedArgs.mServiceArgs == null) {
5170 cachedArgs.mServiceArgs = new ParseComponentArgs(owner, outError,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005171 com.android.internal.R.styleable.AndroidManifestService_name,
5172 com.android.internal.R.styleable.AndroidManifestService_label,
5173 com.android.internal.R.styleable.AndroidManifestService_icon,
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005174 com.android.internal.R.styleable.AndroidManifestService_roundIcon,
Adam Powell81cd2e92010-04-21 16:35:18 -07005175 com.android.internal.R.styleable.AndroidManifestService_logo,
Jose Limaf78e3122014-03-06 12:13:15 -08005176 com.android.internal.R.styleable.AndroidManifestService_banner,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005177 mSeparateProcesses,
5178 com.android.internal.R.styleable.AndroidManifestService_process,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08005179 com.android.internal.R.styleable.AndroidManifestService_description,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005180 com.android.internal.R.styleable.AndroidManifestService_enabled);
Garrett Boyer52136662017-05-23 13:47:58 -07005181 cachedArgs.mServiceArgs.tag = "<service>";
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005182 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005183
Garrett Boyer52136662017-05-23 13:47:58 -07005184 cachedArgs.mServiceArgs.sa = sa;
5185 cachedArgs.mServiceArgs.flags = flags;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005186
Garrett Boyer52136662017-05-23 13:47:58 -07005187 Service s = new Service(cachedArgs.mServiceArgs, new ServiceInfo());
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005188 if (outError[0] != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005189 sa.recycle();
5190 return null;
5191 }
5192
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005193 boolean setExported = sa.hasValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005194 com.android.internal.R.styleable.AndroidManifestService_exported);
5195 if (setExported) {
5196 s.info.exported = sa.getBoolean(
5197 com.android.internal.R.styleable.AndroidManifestService_exported, false);
5198 }
5199
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005200 String str = sa.getNonConfigurationString(
5201 com.android.internal.R.styleable.AndroidManifestService_permission, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005202 if (str == null) {
5203 s.info.permission = owner.applicationInfo.permission;
5204 } else {
5205 s.info.permission = str.length() > 0 ? str.toString().intern() : null;
5206 }
5207
Todd Kennedye9d0d272017-01-23 06:49:29 -08005208 s.info.splitName =
5209 sa.getNonConfigurationString(R.styleable.AndroidManifestService_splitName, 0);
5210
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005211 s.info.flags = 0;
5212 if (sa.getBoolean(
5213 com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
5214 false)) {
5215 s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
5216 }
Dianne Hackborna0c283e2012-02-09 10:47:01 -08005217 if (sa.getBoolean(
5218 com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
5219 false)) {
5220 s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
5221 }
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005222 if (sa.getBoolean(
Robert Sesekb9a86662015-12-09 16:22:45 -05005223 com.android.internal.R.styleable.AndroidManifestService_externalService,
5224 false)) {
5225 s.info.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE;
5226 }
5227 if (sa.getBoolean(
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005228 com.android.internal.R.styleable.AndroidManifestService_singleUser,
5229 false)) {
5230 s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
Dianne Hackbornb4163a62012-08-02 18:31:26 -07005231 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005232
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005233 s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
5234 R.styleable.AndroidManifestService_directBootAware,
Todd Kennedyd022ac22016-04-13 10:49:29 -07005235 false);
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005236 if (s.info.directBootAware) {
Jeff Sharkey8924e872015-11-30 12:52:10 -07005237 owner.applicationInfo.privateFlags |=
Jeff Sharkey8a372a02016-03-16 16:25:45 -06005238 ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
Jeff Sharkey8924e872015-11-30 12:52:10 -07005239 }
Jeff Sharkeye17ac152015-11-06 22:40:29 -08005240
Todd Kennedy752fb702017-03-21 16:28:10 -07005241 boolean visibleToEphemeral =
Todd Kennedybe0b8892017-02-15 14:13:52 -08005242 sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005243 if (visibleToEphemeral) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005244 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07005245 owner.visibleToInstantApps = true;
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005246 }
5247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005248 sa.recycle();
5249
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005250 if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
5251 != 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005252 // A heavy-weight application can not have services in its main process
5253 // We can do direct compare because we intern all strings.
5254 if (s.info.processName == owner.packageName) {
5255 outError[0] = "Heavy-weight applications can not have services in main process";
5256 return null;
5257 }
5258 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005260 int outerDepth = parser.getDepth();
5261 int type;
5262 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5263 && (type != XmlPullParser.END_TAG
5264 || parser.getDepth() > outerDepth)) {
5265 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5266 continue;
5267 }
5268
5269 if (parser.getName().equals("intent-filter")) {
5270 ServiceIntentInfo intent = new ServiceIntentInfo(s);
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005271 if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
5272 intent, outError)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005273 return null;
5274 }
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005275 if (visibleToEphemeral) {
5276 intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
5277 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005279 s.intents.add(intent);
5280 } else if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005281 if ((s.metaData=parseMetaData(res, parser, s.metaData,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005282 outError)) == null) {
5283 return null;
5284 }
Todd Kennedy752fb702017-03-21 16:28:10 -07005285 // we don't have an attribute [or it's false], but, we have meta-data
5286 if (!visibleToEphemeral && s.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
5287 visibleToEphemeral = true; // set in case there are more intent filters
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005288 s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
Todd Kennedy752fb702017-03-21 16:28:10 -07005289 owner.visibleToInstantApps = true;
5290 // cycle through any filters already seen
5291 for (int i = s.intents.size() - 1; i >= 0; --i) {
Todd Kennedyc05f5d12017-04-25 11:11:40 -07005292 s.intents.get(i)
5293 .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
Todd Kennedy752fb702017-03-21 16:28:10 -07005294 }
5295 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005296 } else {
5297 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005298 Slog.w(TAG, "Unknown element under <service>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005299 + parser.getName() + " at " + mArchiveSourcePath + " "
5300 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005301 XmlUtils.skipCurrentTag(parser);
5302 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005303 } else {
5304 outError[0] = "Bad element under <service>: " + parser.getName();
5305 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005306 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005307 }
5308 }
5309
5310 if (!setExported) {
5311 s.info.exported = s.intents.size() > 0;
5312 }
5313
5314 return s;
5315 }
5316
Chad Brubaker49414832017-04-13 16:13:23 -07005317 private boolean isImplicitlyExposedIntent(IntentInfo intent) {
5318 return intent.hasCategory(Intent.CATEGORY_BROWSABLE)
5319 || intent.hasAction(Intent.ACTION_SEND)
5320 || intent.hasAction(Intent.ACTION_SENDTO)
5321 || intent.hasAction(Intent.ACTION_SEND_MULTIPLE);
Todd Kennedy388eb8c2016-12-16 14:40:25 -08005322 }
5323
Svet Ganov354cd3c2015-12-17 11:35:04 -08005324 private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag,
5325 Component<?> outInfo, String[] outError) throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005326 int outerDepth = parser.getDepth();
5327 int type;
5328 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5329 && (type != XmlPullParser.END_TAG
5330 || parser.getDepth() > outerDepth)) {
5331 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
5332 continue;
5333 }
5334
5335 if (parser.getName().equals("meta-data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005336 if ((outInfo.metaData=parseMetaData(res, parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005337 outInfo.metaData, outError)) == null) {
5338 return false;
5339 }
5340 } else {
5341 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005342 Slog.w(TAG, "Unknown element under " + tag + ": "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005343 + parser.getName() + " at " + mArchiveSourcePath + " "
5344 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005345 XmlUtils.skipCurrentTag(parser);
5346 continue;
Kenny Rootd2d29252011-08-08 11:27:57 -07005347 } else {
5348 outError[0] = "Bad element under " + tag + ": " + parser.getName();
5349 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005350 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005351 }
5352 }
5353 return true;
5354 }
5355
5356 private Bundle parseMetaData(Resources res,
Svet Ganov354cd3c2015-12-17 11:35:04 -08005357 XmlResourceParser parser, Bundle data, String[] outError)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005358 throws XmlPullParserException, IOException {
5359
Svet Ganov354cd3c2015-12-17 11:35:04 -08005360 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005361 com.android.internal.R.styleable.AndroidManifestMetaData);
5362
5363 if (data == null) {
5364 data = new Bundle();
5365 }
5366
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005367 String name = sa.getNonConfigurationString(
5368 com.android.internal.R.styleable.AndroidManifestMetaData_name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005369 if (name == null) {
5370 outError[0] = "<meta-data> requires an android:name attribute";
5371 sa.recycle();
5372 return null;
5373 }
5374
Dianne Hackborn854060af2009-07-09 18:14:31 -07005375 name = name.intern();
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005377 TypedValue v = sa.peekValue(
5378 com.android.internal.R.styleable.AndroidManifestMetaData_resource);
5379 if (v != null && v.resourceId != 0) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005380 //Slog.i(TAG, "Meta data ref " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005381 data.putInt(name, v.resourceId);
5382 } else {
5383 v = sa.peekValue(
5384 com.android.internal.R.styleable.AndroidManifestMetaData_value);
Kenny Rootd2d29252011-08-08 11:27:57 -07005385 //Slog.i(TAG, "Meta data " + name + ": " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005386 if (v != null) {
5387 if (v.type == TypedValue.TYPE_STRING) {
5388 CharSequence cs = v.coerceToString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00005389 data.putString(name, cs != null ? cs.toString() : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005390 } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
5391 data.putBoolean(name, v.data != 0);
5392 } else if (v.type >= TypedValue.TYPE_FIRST_INT
5393 && v.type <= TypedValue.TYPE_LAST_INT) {
5394 data.putInt(name, v.data);
5395 } else if (v.type == TypedValue.TYPE_FLOAT) {
5396 data.putFloat(name, v.getFloat());
5397 } else {
5398 if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005399 Slog.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005400 + parser.getName() + " at " + mArchiveSourcePath + " "
5401 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005402 } else {
5403 outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types";
5404 data = null;
5405 }
5406 }
5407 } else {
5408 outError[0] = "<meta-data> requires an android:value or android:resource attribute";
5409 data = null;
5410 }
5411 }
5412
5413 sa.recycle();
5414
5415 XmlUtils.skipCurrentTag(parser);
5416
5417 return data;
5418 }
5419
Adam Lesinski4e862812016-11-21 16:02:24 -08005420 private static VerifierInfo parseVerifier(AttributeSet attrs) {
5421 String packageName = null;
5422 String encodedPublicKey = null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005423
Adam Lesinski4e862812016-11-21 16:02:24 -08005424 final int attrCount = attrs.getAttributeCount();
5425 for (int i = 0; i < attrCount; i++) {
5426 final int attrResId = attrs.getAttributeNameResource(i);
5427 switch (attrResId) {
5428 case com.android.internal.R.attr.name:
5429 packageName = attrs.getAttributeValue(i);
5430 break;
Kenny Root05ca4c92011-09-15 10:36:25 -07005431
Adam Lesinski4e862812016-11-21 16:02:24 -08005432 case com.android.internal.R.attr.publicKey:
5433 encodedPublicKey = attrs.getAttributeValue(i);
5434 break;
5435 }
5436 }
Kenny Root05ca4c92011-09-15 10:36:25 -07005437
5438 if (packageName == null || packageName.length() == 0) {
5439 Slog.i(TAG, "verifier package name was null; skipping");
5440 return null;
Kenny Root05ca4c92011-09-15 10:36:25 -07005441 }
5442
Christopher Tate30147332014-04-15 12:57:47 -07005443 final PublicKey publicKey = parsePublicKey(encodedPublicKey);
5444 if (publicKey == null) {
5445 Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
5446 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -08005447 }
5448
Christopher Tate30147332014-04-15 12:57:47 -07005449 return new VerifierInfo(packageName, publicKey);
Geremy Condraf1bcca82013-01-07 22:35:24 -08005450 }
5451
Christopher Tate30147332014-04-15 12:57:47 -07005452 public static final PublicKey parsePublicKey(final String encodedPublicKey) {
5453 if (encodedPublicKey == null) {
dcashman1616f302015-05-29 14:47:23 -07005454 Slog.w(TAG, "Could not parse null public key");
Christopher Tate30147332014-04-15 12:57:47 -07005455 return null;
5456 }
5457
Kenny Root05ca4c92011-09-15 10:36:25 -07005458 EncodedKeySpec keySpec;
5459 try {
5460 final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
5461 keySpec = new X509EncodedKeySpec(encoded);
5462 } catch (IllegalArgumentException e) {
dcashman1616f302015-05-29 14:47:23 -07005463 Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
Kenny Root05ca4c92011-09-15 10:36:25 -07005464 return null;
5465 }
5466
5467 /* First try the key as an RSA key. */
5468 try {
5469 final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005470 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005471 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005472 Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005473 } catch (InvalidKeySpecException e) {
5474 // Not a RSA public key.
5475 }
5476
dcashman1616f302015-05-29 14:47:23 -07005477 /* Now try it as a ECDSA key. */
5478 try {
5479 final KeyFactory keyFactory = KeyFactory.getInstance("EC");
5480 return keyFactory.generatePublic(keySpec);
5481 } catch (NoSuchAlgorithmException e) {
5482 Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build");
5483 } catch (InvalidKeySpecException e) {
5484 // Not a ECDSA public key.
5485 }
5486
Kenny Root05ca4c92011-09-15 10:36:25 -07005487 /* Now try it as a DSA key. */
5488 try {
5489 final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
Geremy Condraf1bcca82013-01-07 22:35:24 -08005490 return keyFactory.generatePublic(keySpec);
Kenny Root05ca4c92011-09-15 10:36:25 -07005491 } catch (NoSuchAlgorithmException e) {
dcashman1616f302015-05-29 14:47:23 -07005492 Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build");
Kenny Root05ca4c92011-09-15 10:36:25 -07005493 } catch (InvalidKeySpecException e) {
5494 // Not a DSA public key.
5495 }
5496
dcashman1616f302015-05-29 14:47:23 -07005497 /* Not a supported key type */
Kenny Root05ca4c92011-09-15 10:36:25 -07005498 return null;
5499 }
5500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005501 private static final String ANDROID_RESOURCES
5502 = "http://schemas.android.com/apk/res/android";
5503
Todd Kennedy7bc3a702016-12-08 14:54:48 -08005504 private boolean parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs,
5505 boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
5506 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005507
Svet Ganov354cd3c2015-12-17 11:35:04 -08005508 TypedArray sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005509 com.android.internal.R.styleable.AndroidManifestIntentFilter);
5510
5511 int priority = sa.getInt(
5512 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005513 outInfo.setPriority(priority);
Kenny Root502e9a42011-01-10 13:48:15 -08005514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005515 TypedValue v = sa.peekValue(
5516 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
5517 if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
5518 outInfo.nonLocalizedLabel = v.coerceToString();
5519 }
5520
Todd Kennedya83bfca2016-06-03 07:52:17 -07005521 final boolean useRoundIcon =
5522 Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
5523 int roundIconVal = useRoundIcon ? sa.getResourceId(
5524 com.android.internal.R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0;
5525 if (roundIconVal != 0) {
5526 outInfo.icon = roundIconVal;
Todd Kennedybb8a42d2016-06-02 14:13:56 -07005527 } else {
5528 outInfo.icon = sa.getResourceId(
5529 com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
5530 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07005531
Adam Powell81cd2e92010-04-21 16:35:18 -07005532 outInfo.logo = sa.getResourceId(
5533 com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005534
Jose Limaf78e3122014-03-06 12:13:15 -08005535 outInfo.banner = sa.getResourceId(
5536 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
5537
Fabrice Di Meglio1c1b4712014-11-19 17:12:32 -08005538 if (allowAutoVerify) {
5539 outInfo.setAutoVerify(sa.getBoolean(
5540 com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
5541 false));
5542 }
5543
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005544 sa.recycle();
5545
5546 int outerDepth = parser.getDepth();
5547 int type;
Kenny Rootd2d29252011-08-08 11:27:57 -07005548 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
5549 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
5550 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005551 continue;
5552 }
5553
5554 String nodeName = parser.getName();
5555 if (nodeName.equals("action")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005556 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005557 ANDROID_RESOURCES, "name");
5558 if (value == null || value == "") {
5559 outError[0] = "No value supplied for <android:name>";
5560 return false;
5561 }
5562 XmlUtils.skipCurrentTag(parser);
5563
5564 outInfo.addAction(value);
5565 } else if (nodeName.equals("category")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005566 String value = parser.getAttributeValue(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005567 ANDROID_RESOURCES, "name");
5568 if (value == null || value == "") {
5569 outError[0] = "No value supplied for <android:name>";
5570 return false;
5571 }
5572 XmlUtils.skipCurrentTag(parser);
5573
5574 outInfo.addCategory(value);
5575
5576 } else if (nodeName.equals("data")) {
Svet Ganov354cd3c2015-12-17 11:35:04 -08005577 sa = res.obtainAttributes(parser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005578 com.android.internal.R.styleable.AndroidManifestData);
5579
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005580 String str = sa.getNonConfigurationString(
5581 com.android.internal.R.styleable.AndroidManifestData_mimeType, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005582 if (str != null) {
5583 try {
5584 outInfo.addDataType(str);
5585 } catch (IntentFilter.MalformedMimeTypeException e) {
5586 outError[0] = e.toString();
5587 sa.recycle();
5588 return false;
5589 }
5590 }
5591
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005592 str = sa.getNonConfigurationString(
5593 com.android.internal.R.styleable.AndroidManifestData_scheme, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005594 if (str != null) {
5595 outInfo.addDataScheme(str);
5596 }
5597
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005598 str = sa.getNonConfigurationString(
5599 com.android.internal.R.styleable.AndroidManifestData_ssp, 0);
5600 if (str != null) {
5601 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
5602 }
5603
5604 str = sa.getNonConfigurationString(
5605 com.android.internal.R.styleable.AndroidManifestData_sspPrefix, 0);
5606 if (str != null) {
5607 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
5608 }
5609
5610 str = sa.getNonConfigurationString(
5611 com.android.internal.R.styleable.AndroidManifestData_sspPattern, 0);
5612 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005613 if (!allowGlobs) {
5614 outError[0] = "sspPattern not allowed here; ssp must be literal";
5615 return false;
5616 }
Dianne Hackborndf1c0bf2013-06-12 16:21:38 -07005617 outInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5618 }
5619
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005620 String host = sa.getNonConfigurationString(
5621 com.android.internal.R.styleable.AndroidManifestData_host, 0);
5622 String port = sa.getNonConfigurationString(
5623 com.android.internal.R.styleable.AndroidManifestData_port, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005624 if (host != null) {
5625 outInfo.addDataAuthority(host, port);
5626 }
5627
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005628 str = sa.getNonConfigurationString(
5629 com.android.internal.R.styleable.AndroidManifestData_path, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005630 if (str != null) {
5631 outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
5632 }
5633
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005634 str = sa.getNonConfigurationString(
5635 com.android.internal.R.styleable.AndroidManifestData_pathPrefix, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005636 if (str != null) {
5637 outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
5638 }
5639
Dianne Hackborncf244ad2010-03-09 15:00:30 -08005640 str = sa.getNonConfigurationString(
5641 com.android.internal.R.styleable.AndroidManifestData_pathPattern, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005642 if (str != null) {
Dianne Hackbornb09491f2013-07-22 15:30:11 -07005643 if (!allowGlobs) {
5644 outError[0] = "pathPattern not allowed here; path must be literal";
5645 return false;
5646 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005647 outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
5648 }
5649
Todd Kennedy9c9fdf22017-03-06 10:58:27 -08005650 str = sa.getNonConfigurationString(
5651 com.android.internal.R.styleable.AndroidManifestData_pathAdvancedPattern, 0);
5652 if (str != null) {
5653 if (!allowGlobs) {
5654 outError[0] = "pathAdvancedPattern not allowed here; path must be literal";
5655 return false;
5656 }
5657 outInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB);
5658 }
5659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005660 sa.recycle();
5661 XmlUtils.skipCurrentTag(parser);
5662 } else if (!RIGID_PARSER) {
Kenny Rootd2d29252011-08-08 11:27:57 -07005663 Slog.w(TAG, "Unknown element under <intent-filter>: "
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005664 + parser.getName() + " at " + mArchiveSourcePath + " "
5665 + parser.getPositionDescription());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005666 XmlUtils.skipCurrentTag(parser);
5667 } else {
5668 outError[0] = "Bad element under <intent-filter>: " + parser.getName();
5669 return false;
5670 }
5671 }
5672
5673 outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT);
Kenny Rootd2d29252011-08-08 11:27:57 -07005674
5675 if (DEBUG_PARSER) {
5676 final StringBuilder cats = new StringBuilder("Intent d=");
5677 cats.append(outInfo.hasDefault);
5678 cats.append(", cat=");
5679
5680 final Iterator<String> it = outInfo.categoriesIterator();
5681 if (it != null) {
5682 while (it.hasNext()) {
5683 cats.append(' ');
5684 cats.append(it.next());
5685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005686 }
Kenny Rootd2d29252011-08-08 11:27:57 -07005687 Slog.d(TAG, cats.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005688 }
5689
5690 return true;
5691 }
5692
Patrick Baumann47117fc2017-12-19 10:17:21 -08005693 /** A container for signing-related data of an application package. */
5694 public static final class SigningDetails implements Parcelable {
5695
5696 @IntDef({SigningDetails.SignatureSchemeVersion.UNKNOWN,
5697 SigningDetails.SignatureSchemeVersion.JAR,
5698 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2,
5699 SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3})
5700 public @interface SignatureSchemeVersion {
5701 int UNKNOWN = 0;
5702 int JAR = 1;
5703 int SIGNING_BLOCK_V2 = 2;
5704 int SIGNING_BLOCK_V3 = 3;
5705 }
5706
5707 @Nullable
5708 public final Signature[] signatures;
5709 @SignatureSchemeVersion
5710 public final int signatureSchemeVersion;
5711 @Nullable
5712 public final ArraySet<PublicKey> publicKeys;
5713
Daniel Cashman77029c52018-01-18 16:19:29 -08005714 /**
5715 * Collection of {@code Signature} objects, each of which is formed from a former signing
5716 * certificate of this APK before it was changed by signing certificate rotation.
5717 */
5718 @Nullable
5719 public final Signature[] pastSigningCertificates;
5720
5721 /**
5722 * Flags for the {@code pastSigningCertificates} collection, which indicate the capabilities
5723 * the including APK wishes to grant to its past signing certificates.
5724 */
5725 @Nullable
5726 public final int[] pastSigningCertificatesFlags;
5727
Patrick Baumann47117fc2017-12-19 10:17:21 -08005728 /** A representation of unknown signing details. Use instead of null. */
5729 public static final SigningDetails UNKNOWN =
Daniel Cashman77029c52018-01-18 16:19:29 -08005730 new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null, null, null);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005731
5732 @VisibleForTesting
5733 public SigningDetails(Signature[] signatures,
5734 @SignatureSchemeVersion int signatureSchemeVersion,
Daniel Cashman77029c52018-01-18 16:19:29 -08005735 ArraySet<PublicKey> keys, Signature[] pastSigningCertificates,
5736 int[] pastSigningCertificatesFlags) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08005737 this.signatures = signatures;
5738 this.signatureSchemeVersion = signatureSchemeVersion;
5739 this.publicKeys = keys;
Daniel Cashman77029c52018-01-18 16:19:29 -08005740 this.pastSigningCertificates = pastSigningCertificates;
5741 this.pastSigningCertificatesFlags = pastSigningCertificatesFlags;
5742 }
5743
5744 public SigningDetails(Signature[] signatures,
5745 @SignatureSchemeVersion int signatureSchemeVersion,
5746 Signature[] pastSigningCertificates, int[] pastSigningCertificatesFlags)
5747 throws CertificateException {
5748 this(signatures, signatureSchemeVersion, toSigningKeys(signatures),
5749 pastSigningCertificates, pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005750 }
5751
5752 public SigningDetails(Signature[] signatures,
5753 @SignatureSchemeVersion int signatureSchemeVersion)
5754 throws CertificateException {
Daniel Cashman77029c52018-01-18 16:19:29 -08005755 this(signatures, signatureSchemeVersion,
5756 null, null);
5757 }
5758
5759 public SigningDetails(SigningDetails orig) {
5760 if (orig != null) {
5761 if (orig.signatures != null) {
5762 this.signatures = orig.signatures.clone();
5763 } else {
5764 this.signatures = null;
5765 }
5766 this.signatureSchemeVersion = orig.signatureSchemeVersion;
5767 this.publicKeys = new ArraySet<>(orig.publicKeys);
5768 if (orig.pastSigningCertificates != null) {
5769 this.pastSigningCertificates = orig.pastSigningCertificates.clone();
5770 this.pastSigningCertificatesFlags = orig.pastSigningCertificatesFlags.clone();
5771 } else {
5772 this.pastSigningCertificates = null;
5773 this.pastSigningCertificatesFlags = null;
5774 }
5775 } else {
5776 this.signatures = null;
5777 this.signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
5778 this.publicKeys = null;
5779 this.pastSigningCertificates = null;
5780 this.pastSigningCertificatesFlags = null;
5781 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08005782 }
5783
5784 /** Returns true if the signing details have one or more signatures. */
5785 public boolean hasSignatures() {
5786 return signatures != null && signatures.length > 0;
5787 }
5788
Daniel Cashman5cdda342018-01-19 07:22:52 -08005789 /** Returns true if the signing details have past signing certificates. */
5790 public boolean hasPastSigningCertificates() {
5791 return pastSigningCertificates != null && pastSigningCertificates.length > 0;
5792 }
5793
Patrick Baumann47117fc2017-12-19 10:17:21 -08005794 /** Returns true if the signatures in this and other match exactly. */
5795 public boolean signaturesMatchExactly(SigningDetails other) {
5796 return Signature.areExactMatch(this.signatures, other.signatures);
5797 }
5798
5799 @Override
5800 public int describeContents() {
5801 return 0;
5802 }
5803
5804 @Override
5805 public void writeToParcel(Parcel dest, int flags) {
5806 boolean isUnknown = UNKNOWN == this;
5807 dest.writeBoolean(isUnknown);
5808 if (isUnknown) {
5809 return;
5810 }
5811 dest.writeTypedArray(this.signatures, flags);
5812 dest.writeInt(this.signatureSchemeVersion);
5813 dest.writeArraySet(this.publicKeys);
Daniel Cashman77029c52018-01-18 16:19:29 -08005814 dest.writeTypedArray(this.pastSigningCertificates, flags);
5815 dest.writeIntArray(this.pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005816 }
5817
5818 protected SigningDetails(Parcel in) {
5819 final ClassLoader boot = Object.class.getClassLoader();
5820 this.signatures = in.createTypedArray(Signature.CREATOR);
5821 this.signatureSchemeVersion = in.readInt();
5822 this.publicKeys = (ArraySet<PublicKey>) in.readArraySet(boot);
Daniel Cashman77029c52018-01-18 16:19:29 -08005823 this.pastSigningCertificates = in.createTypedArray(Signature.CREATOR);
5824 this.pastSigningCertificatesFlags = in.createIntArray();
Patrick Baumann47117fc2017-12-19 10:17:21 -08005825 }
5826
5827 public static final Creator<SigningDetails> CREATOR = new Creator<SigningDetails>() {
5828 @Override
5829 public SigningDetails createFromParcel(Parcel source) {
5830 if (source.readBoolean()) {
5831 return UNKNOWN;
5832 }
5833 return new SigningDetails(source);
5834 }
5835
5836 @Override
5837 public SigningDetails[] newArray(int size) {
5838 return new SigningDetails[size];
5839 }
5840 };
5841
5842 @Override
5843 public boolean equals(Object o) {
5844 if (this == o) return true;
5845 if (!(o instanceof SigningDetails)) return false;
5846
5847 SigningDetails that = (SigningDetails) o;
5848
5849 if (signatureSchemeVersion != that.signatureSchemeVersion) return false;
5850 if (!Signature.areExactMatch(signatures, that.signatures)) return false;
Daniel Cashman77029c52018-01-18 16:19:29 -08005851 if (publicKeys != null) {
5852 if (!publicKeys.equals((that.publicKeys))) {
5853 return false;
5854 }
5855 } else if (that.publicKeys != null) {
5856 return false;
5857 }
5858
5859 // can't use Signature.areExactMatch() because order matters with the past signing certs
5860 if (!Arrays.equals(pastSigningCertificates, that.pastSigningCertificates)) {
5861 return false;
5862 }
5863 if (!Arrays.equals(pastSigningCertificatesFlags, that.pastSigningCertificatesFlags)) {
5864 return false;
5865 }
5866
5867 return true;
Patrick Baumann47117fc2017-12-19 10:17:21 -08005868 }
5869
5870 @Override
5871 public int hashCode() {
5872 int result = +Arrays.hashCode(signatures);
5873 result = 31 * result + signatureSchemeVersion;
5874 result = 31 * result + (publicKeys != null ? publicKeys.hashCode() : 0);
Daniel Cashman77029c52018-01-18 16:19:29 -08005875 result = 31 * result + Arrays.hashCode(pastSigningCertificates);
5876 result = 31 * result + Arrays.hashCode(pastSigningCertificatesFlags);
Patrick Baumann47117fc2017-12-19 10:17:21 -08005877 return result;
5878 }
Daniel Cashman77029c52018-01-18 16:19:29 -08005879
5880 /**
5881 * Builder of {@code SigningDetails} instances.
5882 */
5883 public static class Builder {
5884 private Signature[] mSignatures;
5885 private int mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
5886 private Signature[] mPastSigningCertificates;
5887 private int[] mPastSigningCertificatesFlags;
5888
5889 public Builder() {
5890 }
5891
5892 /** get signing certificates used to sign the current APK */
5893 public Builder setSignatures(Signature[] signatures) {
5894 mSignatures = signatures;
5895 return this;
5896 }
5897
5898 /** set the signature scheme version used to sign the APK */
5899 public Builder setSignatureSchemeVersion(int signatureSchemeVersion) {
5900 mSignatureSchemeVersion = signatureSchemeVersion;
5901 return this;
5902 }
5903
5904 /** set the signing certificates by which the APK proved it can be authenticated */
5905 public Builder setPastSigningCertificates(Signature[] pastSigningCertificates) {
5906 mPastSigningCertificates = pastSigningCertificates;
5907 return this;
5908 }
5909
5910 /** set the flags for the {@code pastSigningCertificates} */
5911 public Builder setPastSigningCertificatesFlags(int[] pastSigningCertificatesFlags) {
5912 mPastSigningCertificatesFlags = pastSigningCertificatesFlags;
5913 return this;
5914 }
5915
5916 private void checkInvariants() {
5917 // must have signatures and scheme version set
5918 if (mSignatures == null) {
5919 throw new IllegalStateException("SigningDetails requires the current signing"
5920 + " certificates.");
5921 }
5922
5923 // pastSigningCerts and flags must match up
5924 boolean pastMismatch = false;
5925 if (mPastSigningCertificates != null && mPastSigningCertificatesFlags != null) {
5926 if (mPastSigningCertificates.length != mPastSigningCertificatesFlags.length) {
5927 pastMismatch = true;
5928 }
5929 } else if (!(mPastSigningCertificates == null
5930 && mPastSigningCertificatesFlags == null)) {
5931 pastMismatch = true;
5932 }
5933 if (pastMismatch) {
5934 throw new IllegalStateException("SigningDetails must have a one to one mapping "
5935 + "between pastSigningCertificates and pastSigningCertificatesFlags");
5936 }
5937 }
5938 /** build a {@code SigningDetails} object */
5939 public SigningDetails build()
5940 throws CertificateException {
5941 checkInvariants();
5942 return new SigningDetails(mSignatures, mSignatureSchemeVersion,
5943 mPastSigningCertificates, mPastSigningCertificatesFlags);
5944 }
5945 }
Patrick Baumann47117fc2017-12-19 10:17:21 -08005946 }
5947
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005948 /**
5949 * Representation of a full package parsed from APK files on disk. A package
5950 * consists of a single base APK, and zero or more split APKs.
5951 */
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00005952 public final static class Package implements Parcelable {
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07005953
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005954 public String packageName;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08005955
Svet Ganov67882122016-12-11 16:36:34 -08005956 // The package name declared in the manifest as the package can be
5957 // renamed, for example static shared libs use synthetic package names.
5958 public String manifestPackageName;
5959
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005960 /** Names of any split APKs, ordered by parsed splitName */
5961 public String[] splitNames;
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005962
5963 // TODO: work towards making these paths invariant
Jeff Sharkey275e0852014-06-17 18:18:49 -07005964
Jeff Sharkeyb9f36742015-04-08 21:02:14 -07005965 public String volumeUuid;
5966
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005967 /**
5968 * Path where this package was found on disk. For monolithic packages
5969 * this is path to single base APK file; for cluster packages this is
5970 * path to the cluster directory.
5971 */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005972 public String codePath;
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07005973
5974 /** Path of base APK */
5975 public String baseCodePath;
5976 /** Paths of any split APKs, ordered by parsed splitName */
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07005977 public String[] splitCodePaths;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005978
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08005979 /** Revision code of base APK */
5980 public int baseRevisionCode;
5981 /** Revision codes of any split APKs, ordered by parsed splitName */
5982 public int[] splitRevisionCodes;
5983
Jeff Sharkeyda96e132014-07-15 14:54:09 -07005984 /** Flags of any split APKs; ordered by parsed splitName */
5985 public int[] splitFlags;
5986
Alex Klyubinb9f8a522015-02-03 11:12:59 -08005987 /**
5988 * Private flags of any split APKs; ordered by parsed splitName.
5989 *
5990 * {@hide}
5991 */
5992 public int[] splitPrivateFlags;
5993
Jeff Sharkeyda96e132014-07-15 14:54:09 -07005994 public boolean baseHardwareAccelerated;
5995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005996 // For now we only support one application per package.
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00005997 public ApplicationInfo applicationInfo = new ApplicationInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005998
5999 public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
6000 public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
6001 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
6002 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
6003 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
6004 public final ArrayList<Service> services = new ArrayList<Service>(0);
6005 public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
6006
6007 public final ArrayList<String> requestedPermissions = new ArrayList<String>();
6008
Dianne Hackborn854060af2009-07-09 18:14:31 -07006009 public ArrayList<String> protectedBroadcasts;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006010
Svet Ganov354cd3c2015-12-17 11:35:04 -08006011 public Package parentPackage;
6012 public ArrayList<Package> childPackages;
6013
Svet Ganov67882122016-12-11 16:36:34 -08006014 public String staticSharedLibName = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006015 public long staticSharedLibVersion = 0;
Dianne Hackbornc895be72013-03-11 17:48:43 -07006016 public ArrayList<String> libraryNames = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07006017 public ArrayList<String> usesLibraries = null;
Svet Ganov67882122016-12-11 16:36:34 -08006018 public ArrayList<String> usesStaticLibraries = null;
Dianne Hackborn3accca02013-09-20 09:32:11 -07006019 public long[] usesStaticLibrariesVersions = null;
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006020 public String[][] usesStaticLibrariesCertDigests = null;
Dianne Hackborn49237342009-08-27 20:08:01 -07006021 public ArrayList<String> usesOptionalLibraries = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006022 public String[] usesLibraryFiles = null;
6023
Dianne Hackbornb09491f2013-07-22 15:30:11 -07006024 public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
6025
Dianne Hackbornc1552392010-03-03 16:19:01 -08006026 public ArrayList<String> mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006027 public String mRealPackage = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006028 public ArrayList<String> mAdoptPermissions = null;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006029
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006030 // We store the application meta-data independently to avoid multiple unwanted references
6031 public Bundle mAppMetaData = null;
6032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006033 // The version code declared for this package.
6034 public int mVersionCode;
Jeff Sharkey88d2a3c2014-11-22 16:49:34 -08006035
Dianne Hackborn3accca02013-09-20 09:32:11 -07006036 // The major version code declared for this package.
6037 public int mVersionCodeMajor;
6038
6039 // Return long containing mVersionCode and mVersionCodeMajor.
6040 public long getLongVersionCode() {
6041 return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
6042 }
6043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006044 // The version name declared for this package.
6045 public String mVersionName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006047 // The shared user id that this package wants to use.
6048 public String mSharedUserId;
6049
6050 // The shared user label that this package wants to use.
6051 public int mSharedUserLabel;
6052
6053 // Signatures that were read from the package.
Patrick Baumann47117fc2017-12-19 10:17:21 -08006054 @NonNull public SigningDetails mSigningDetails = SigningDetails.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006055
6056 // For use by package manager service for quick lookup of
6057 // preferred up order.
6058 public int mPreferredOrder = 0;
6059
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006060 // For use by package manager to keep track of when a package was last used.
Brian Carlstromca82e612016-04-19 23:16:08 -07006061 public long[] mLastPackageUsageTimeInMills =
6062 new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
Brian Carlstromff1ec4d2014-03-17 15:21:35 -07006063
Amith Yamasani13593602012-03-22 16:16:17 -07006064 // // User set enabled state.
6065 // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
6066 //
6067 // // Whether the package has been stopped.
6068 // public boolean mSetStopped = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -08006069
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006070 // Additional data supplied by callers.
6071 public Object mExtras;
Kenny Rootdeb11262010-08-02 11:36:21 -07006072
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006073 // Applications hardware preferences
6074 public ArrayList<ConfigurationInfo> configPreferences = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006075
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006076 // Applications requested features
Dianne Hackborn49237342009-08-27 20:08:01 -07006077 public ArrayList<FeatureInfo> reqFeatures = null;
6078
Adam Lesinskid3edfde2014-08-08 17:32:44 -07006079 // Applications requested feature groups
6080 public ArrayList<FeatureGroupInfo> featureGroups = null;
6081
Suchi Amalapurapu117818e2010-02-09 03:45:40 -08006082 public int installLocation;
6083
Jeff Hao272bf3a2014-10-08 13:34:43 -07006084 public boolean coreApp;
6085
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08006086 /* An app that's required for all users and cannot be uninstalled for a user */
6087 public boolean mRequiredForAllUsers;
6088
Amith Yamasani0ac1fc92013-03-27 18:56:08 -07006089 /* The restricted account authenticator type that is used by this application */
6090 public String mRestrictedAccountType;
6091
Amith Yamasaniccbe3892013-04-12 17:52:42 -07006092 /* The required account type without which this application will not function */
6093 public String mRequiredAccountType;
6094
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006095 public String mOverlayTarget;
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006096 public int mOverlayPriority;
Jaekyun Seok04342892017-03-02 15:24:19 +09006097 public boolean mIsStaticOverlay;
MÃ¥rten Kongstad48d22322014-01-31 14:43:27 +01006098 public boolean mTrustedOverlay;
6099
Alan Viveretteb6a25732017-11-21 14:49:24 -05006100 public int mCompileSdkVersion;
6101 public String mCompileSdkVersionCodename;
6102
Geremy Condraf1bcca82013-01-07 22:35:24 -08006103 /**
dcashman989eb3712014-06-17 12:56:12 -07006104 * Data used to feed the KeySetManagerService
Geremy Condraf1bcca82013-01-07 22:35:24 -08006105 */
dcashman989eb3712014-06-17 12:56:12 -07006106 public ArraySet<String> mUpgradeKeySets;
6107 public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -08006108
Narayan Kamath4903f642014-08-11 13:33:45 +01006109 /**
6110 * The install time abi override for this package, if any.
6111 *
6112 * TODO: This seems like a horrible place to put the abiOverride because
6113 * this isn't something the packageParser parsers. However, this fits in with
6114 * the rest of the PackageManager where package scanning randomly pushes
6115 * and prods fields out of {@code this.applicationInfo}.
6116 */
6117 public String cpuAbiOverride;
Selim Gurun2d291d82016-02-05 17:50:53 -08006118 /**
6119 * The install time abi override to choose 32bit abi's when multiple abi's
6120 * are present. This is only meaningfull for multiarch applications.
6121 * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
6122 */
6123 public boolean use32bitAbi;
Narayan Kamath4903f642014-08-11 13:33:45 +01006124
Todd Kennedyfdd241a2016-04-28 12:26:53 -07006125 public byte[] restrictUpdateHash;
6126
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006127 /** Set if the app or any of its components are visible to instant applications. */
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006128 public boolean visibleToInstantApps;
Todd Kennedy7c8addf2017-06-27 14:13:55 -07006129 /** Whether or not the package is a stub and must be replaced by the full version. */
6130 public boolean isStub;
Chad Brubaker06ca1e02017-03-16 17:56:25 -07006131
Jeff Sharkeyc4858a22014-06-16 10:51:20 -07006132 public Package(String packageName) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006133 this.packageName = packageName;
Svet Ganov67882122016-12-11 16:36:34 -08006134 this.manifestPackageName = packageName;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07006135 applicationInfo.packageName = packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006136 applicationInfo.uid = -1;
6137 }
6138
Svet Ganov354cd3c2015-12-17 11:35:04 -08006139 public void setApplicationVolumeUuid(String volumeUuid) {
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006140 final UUID storageUuid = StorageManager.convert(volumeUuid);
Svet Ganov354cd3c2015-12-17 11:35:04 -08006141 this.applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006142 this.applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006143 if (childPackages != null) {
6144 final int packageCount = childPackages.size();
6145 for (int i = 0; i < packageCount; i++) {
6146 childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
Jeff Sharkey789a8fc2017-04-16 13:18:35 -06006147 childPackages.get(i).applicationInfo.storageUuid = storageUuid;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006148 }
6149 }
6150 }
6151
6152 public void setApplicationInfoCodePath(String codePath) {
6153 this.applicationInfo.setCodePath(codePath);
6154 if (childPackages != null) {
6155 final int packageCount = childPackages.size();
6156 for (int i = 0; i < packageCount; i++) {
6157 childPackages.get(i).applicationInfo.setCodePath(codePath);
6158 }
6159 }
6160 }
6161
Todd Kennedy30a23a52018-01-04 13:27:49 -08006162 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6163 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006164 public void setApplicationInfoResourcePath(String resourcePath) {
6165 this.applicationInfo.setResourcePath(resourcePath);
6166 if (childPackages != null) {
6167 final int packageCount = childPackages.size();
6168 for (int i = 0; i < packageCount; i++) {
6169 childPackages.get(i).applicationInfo.setResourcePath(resourcePath);
6170 }
6171 }
6172 }
6173
Todd Kennedy30a23a52018-01-04 13:27:49 -08006174 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6175 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006176 public void setApplicationInfoBaseResourcePath(String resourcePath) {
6177 this.applicationInfo.setBaseResourcePath(resourcePath);
6178 if (childPackages != null) {
6179 final int packageCount = childPackages.size();
6180 for (int i = 0; i < packageCount; i++) {
6181 childPackages.get(i).applicationInfo.setBaseResourcePath(resourcePath);
6182 }
6183 }
6184 }
6185
6186 public void setApplicationInfoBaseCodePath(String baseCodePath) {
6187 this.applicationInfo.setBaseCodePath(baseCodePath);
6188 if (childPackages != null) {
6189 final int packageCount = childPackages.size();
6190 for (int i = 0; i < packageCount; i++) {
6191 childPackages.get(i).applicationInfo.setBaseCodePath(baseCodePath);
6192 }
6193 }
6194 }
6195
Todd Kennedy13715d52016-08-01 13:38:57 -07006196 public List<String> getChildPackageNames() {
6197 if (childPackages == null) {
6198 return null;
6199 }
6200 final int childCount = childPackages.size();
6201 final List<String> childPackageNames = new ArrayList<>(childCount);
6202 for (int i = 0; i < childCount; i++) {
6203 String childPackageName = childPackages.get(i).packageName;
6204 childPackageNames.add(childPackageName);
6205 }
6206 return childPackageNames;
6207 }
6208
Svet Ganov354cd3c2015-12-17 11:35:04 -08006209 public boolean hasChildPackage(String packageName) {
6210 final int childCount = (childPackages != null) ? childPackages.size() : 0;
6211 for (int i = 0; i < childCount; i++) {
6212 if (childPackages.get(i).packageName.equals(packageName)) {
6213 return true;
6214 }
6215 }
6216 return false;
6217 }
6218
6219 public void setApplicationInfoSplitCodePaths(String[] splitCodePaths) {
6220 this.applicationInfo.setSplitCodePaths(splitCodePaths);
6221 // Children have no splits
6222 }
6223
Todd Kennedy30a23a52018-01-04 13:27:49 -08006224 /** @deprecated Forward locked apps no longer supported. Resource path not needed. */
6225 @Deprecated
Svet Ganov354cd3c2015-12-17 11:35:04 -08006226 public void setApplicationInfoSplitResourcePaths(String[] resroucePaths) {
6227 this.applicationInfo.setSplitResourcePaths(resroucePaths);
6228 // Children have no splits
6229 }
6230
6231 public void setSplitCodePaths(String[] codePaths) {
6232 this.splitCodePaths = codePaths;
6233 }
6234
6235 public void setCodePath(String codePath) {
6236 this.codePath = codePath;
6237 if (childPackages != null) {
6238 final int packageCount = childPackages.size();
6239 for (int i = 0; i < packageCount; i++) {
6240 childPackages.get(i).codePath = codePath;
6241 }
6242 }
6243 }
6244
6245 public void setBaseCodePath(String baseCodePath) {
6246 this.baseCodePath = baseCodePath;
6247 if (childPackages != null) {
6248 final int packageCount = childPackages.size();
6249 for (int i = 0; i < packageCount; i++) {
6250 childPackages.get(i).baseCodePath = baseCodePath;
6251 }
6252 }
6253 }
6254
Patrick Baumann47117fc2017-12-19 10:17:21 -08006255 /** Sets signing details on the package and any of its children. */
6256 public void setSigningDetails(@NonNull SigningDetails signingDetails) {
6257 mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006258 if (childPackages != null) {
6259 final int packageCount = childPackages.size();
6260 for (int i = 0; i < packageCount; i++) {
Patrick Baumann47117fc2017-12-19 10:17:21 -08006261 childPackages.get(i).mSigningDetails = signingDetails;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006262 }
6263 }
6264 }
6265
6266 public void setVolumeUuid(String volumeUuid) {
6267 this.volumeUuid = volumeUuid;
6268 if (childPackages != null) {
6269 final int packageCount = childPackages.size();
6270 for (int i = 0; i < packageCount; i++) {
6271 childPackages.get(i).volumeUuid = volumeUuid;
6272 }
6273 }
6274 }
6275
6276 public void setApplicationInfoFlags(int mask, int flags) {
6277 applicationInfo.flags = (applicationInfo.flags & ~mask) | (mask & flags);
6278 if (childPackages != null) {
6279 final int packageCount = childPackages.size();
6280 for (int i = 0; i < packageCount; i++) {
6281 childPackages.get(i).applicationInfo.flags =
6282 (applicationInfo.flags & ~mask) | (mask & flags);
6283 }
6284 }
6285 }
6286
Selim Gurun75827b22016-02-09 10:55:33 -08006287 public void setUse32bitAbi(boolean use32bitAbi) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006288 this.use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006289 if (childPackages != null) {
6290 final int packageCount = childPackages.size();
6291 for (int i = 0; i < packageCount; i++) {
Selim Gurun2d291d82016-02-05 17:50:53 -08006292 childPackages.get(i).use32bitAbi = use32bitAbi;
Svet Ganov354cd3c2015-12-17 11:35:04 -08006293 }
6294 }
6295 }
6296
Svetoslav Ganov40610e32017-06-20 19:35:51 -07006297 public boolean isLibrary() {
6298 return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames);
6299 }
6300
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006301 public List<String> getAllCodePaths() {
Jeff Sharkey275e0852014-06-17 18:18:49 -07006302 ArrayList<String> paths = new ArrayList<>();
Jeff Sharkey57dcf5b2014-06-18 17:46:05 -07006303 paths.add(baseCodePath);
Jeff Sharkey275e0852014-06-17 18:18:49 -07006304 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6305 Collections.addAll(paths, splitCodePaths);
6306 }
6307 return paths;
6308 }
6309
Jeff Sharkeyda96e132014-07-15 14:54:09 -07006310 /**
6311 * Filtered set of {@link #getAllCodePaths()} that excludes
6312 * resource-only APKs.
6313 */
6314 public List<String> getAllCodePathsExcludingResourceOnly() {
6315 ArrayList<String> paths = new ArrayList<>();
6316 if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6317 paths.add(baseCodePath);
6318 }
6319 if (!ArrayUtils.isEmpty(splitCodePaths)) {
6320 for (int i = 0; i < splitCodePaths.length; i++) {
6321 if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
6322 paths.add(splitCodePaths[i]);
6323 }
6324 }
6325 }
6326 return paths;
6327 }
6328
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006329 public void setPackageName(String newName) {
6330 packageName = newName;
6331 applicationInfo.packageName = newName;
6332 for (int i=permissions.size()-1; i>=0; i--) {
6333 permissions.get(i).setPackageName(newName);
6334 }
6335 for (int i=permissionGroups.size()-1; i>=0; i--) {
6336 permissionGroups.get(i).setPackageName(newName);
6337 }
6338 for (int i=activities.size()-1; i>=0; i--) {
6339 activities.get(i).setPackageName(newName);
6340 }
6341 for (int i=receivers.size()-1; i>=0; i--) {
6342 receivers.get(i).setPackageName(newName);
6343 }
6344 for (int i=providers.size()-1; i>=0; i--) {
6345 providers.get(i).setPackageName(newName);
6346 }
6347 for (int i=services.size()-1; i>=0; i--) {
6348 services.get(i).setPackageName(newName);
6349 }
6350 for (int i=instrumentation.size()-1; i>=0; i--) {
6351 instrumentation.get(i).setPackageName(newName);
6352 }
6353 }
Dianne Hackborn65696252012-03-05 18:49:21 -08006354
6355 public boolean hasComponentClassName(String name) {
6356 for (int i=activities.size()-1; i>=0; i--) {
6357 if (name.equals(activities.get(i).className)) {
6358 return true;
6359 }
6360 }
6361 for (int i=receivers.size()-1; i>=0; i--) {
6362 if (name.equals(receivers.get(i).className)) {
6363 return true;
6364 }
6365 }
6366 for (int i=providers.size()-1; i>=0; i--) {
6367 if (name.equals(providers.get(i).className)) {
6368 return true;
6369 }
6370 }
6371 for (int i=services.size()-1; i>=0; i--) {
6372 if (name.equals(services.get(i).className)) {
6373 return true;
6374 }
6375 }
6376 for (int i=instrumentation.size()-1; i>=0; i--) {
6377 if (name.equals(instrumentation.get(i).className)) {
6378 return true;
6379 }
6380 }
6381 return false;
6382 }
6383
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006384 /** @hide */
6385 public boolean isExternal() {
6386 return applicationInfo.isExternal();
6387 }
6388
6389 /** @hide */
Fyodor Kupoloveeea67b2015-02-23 17:14:45 -08006390 public boolean isForwardLocked() {
6391 return applicationInfo.isForwardLocked();
6392 }
6393
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006394 /** @hide */
6395 public boolean isOem() {
6396 return applicationInfo.isOem();
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006397 }
6398
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006399 /** @hide */
Jiyong Park002fdbd2017-02-13 20:50:31 +09006400 public boolean isVendor() {
6401 return applicationInfo.isVendor();
6402 }
6403
6404 /** @hide */
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006405 public boolean isPrivileged() {
Svet Ganovadc1cf42015-06-15 16:36:24 -07006406 return applicationInfo.isPrivilegedApp();
6407 }
6408
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006409 /** @hide */
6410 public boolean isSystem() {
6411 return applicationInfo.isSystemApp();
6412 }
6413
6414 /** @hide */
Fyodor Kupolovb94c1652015-03-03 12:25:30 -08006415 public boolean isUpdatedSystemApp() {
6416 return applicationInfo.isUpdatedSystemApp();
6417 }
6418
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006419 /** @hide */
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006420 public boolean canHaveOatDir() {
6421 // The following app types CANNOT have oat directory
6422 // - non-updated system apps
6423 // - forward-locked apps or apps installed in ASEC containers
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006424 return (!isSystem() || isUpdatedSystemApp())
Fyodor Kupolovebcac162015-09-09 15:56:45 -07006425 && !isForwardLocked() && !applicationInfo.isExternalAsec();
6426 }
6427
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006428 public boolean isMatch(int flags) {
6429 if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
Todd Kennedyc29b11a2017-10-23 15:55:59 -07006430 return isSystem();
Jeff Sharkeyc5967e92016-01-07 18:50:29 -07006431 }
6432 return true;
6433 }
6434
Brian Carlstromca82e612016-04-19 23:16:08 -07006435 public long getLatestPackageUseTimeInMills() {
6436 long latestUse = 0L;
6437 for (long use : mLastPackageUsageTimeInMills) {
6438 latestUse = Math.max(latestUse, use);
6439 }
6440 return latestUse;
6441 }
6442
David Brazdil90e26992016-04-18 14:08:52 +01006443 public long getLatestForegroundPackageUseTimeInMills() {
6444 int[] foregroundReasons = {
6445 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
6446 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
6447 };
6448
6449 long latestUse = 0L;
6450 for (int reason : foregroundReasons) {
6451 latestUse = Math.max(latestUse, mLastPackageUsageTimeInMills[reason]);
6452 }
6453 return latestUse;
6454 }
6455
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006456 public String toString() {
6457 return "Package{"
6458 + Integer.toHexString(System.identityHashCode(this))
6459 + " " + packageName + "}";
6460 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006461
Todd Kennedyf996b762018-01-12 15:03:29 -08006462 public String dumpState_temp() {
6463 String flags = "";
6464 flags += ((applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 ? "U" : "");
6465 flags += ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 ? "S" : "");
6466 if ("".equals(flags)) {
6467 flags = "-";
6468 }
6469 String privFlags = "";
6470 privFlags += ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0 ? "P" : "");
6471 privFlags += ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0 ? "O" : "");
6472 privFlags += ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0 ? "V" : "");
6473 if ("".equals(privFlags)) {
6474 privFlags = "-";
6475 }
6476 return "Package{"
6477 + Integer.toHexString(System.identityHashCode(this))
6478 + " " + packageName
6479 + ", ver:" + getLongVersionCode()
6480 + ", path: " + codePath
6481 + ", flags: " + flags
6482 + ", privFlags: " + privFlags
6483 + ", extra: " + (mExtras == null ? "<<NULL>>" : Integer.toHexString(System.identityHashCode(mExtras)) + "}")
6484 + "}";
6485 }
6486
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006487 @Override
6488 public int describeContents() {
6489 return 0;
6490 }
6491
6492 public Package(Parcel dest) {
6493 // We use the boot classloader for all classes that we load.
6494 final ClassLoader boot = Object.class.getClassLoader();
6495
Narayan Kamath07ac1442017-02-10 15:08:07 +00006496 packageName = dest.readString().intern();
Svet Ganov67882122016-12-11 16:36:34 -08006497 manifestPackageName = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006498 splitNames = dest.readStringArray();
6499 volumeUuid = dest.readString();
6500 codePath = dest.readString();
6501 baseCodePath = dest.readString();
6502 splitCodePaths = dest.readStringArray();
6503 baseRevisionCode = dest.readInt();
6504 splitRevisionCodes = dest.createIntArray();
6505 splitFlags = dest.createIntArray();
6506 splitPrivateFlags = dest.createIntArray();
6507 baseHardwareAccelerated = (dest.readInt() == 1);
6508 applicationInfo = dest.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006509 if (applicationInfo.permission != null) {
6510 applicationInfo.permission = applicationInfo.permission.intern();
6511 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006512
6513 // We don't serialize the "owner" package and the application info object for each of
6514 // these components, in order to save space and to avoid circular dependencies while
6515 // serialization. We need to fix them all up here.
6516 dest.readParcelableList(permissions, boot);
6517 fixupOwner(permissions);
6518 dest.readParcelableList(permissionGroups, boot);
6519 fixupOwner(permissionGroups);
6520 dest.readParcelableList(activities, boot);
6521 fixupOwner(activities);
6522 dest.readParcelableList(receivers, boot);
6523 fixupOwner(receivers);
6524 dest.readParcelableList(providers, boot);
6525 fixupOwner(providers);
6526 dest.readParcelableList(services, boot);
6527 fixupOwner(services);
6528 dest.readParcelableList(instrumentation, boot);
6529 fixupOwner(instrumentation);
6530
6531 dest.readStringList(requestedPermissions);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006532 internStringArrayList(requestedPermissions);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006533 protectedBroadcasts = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006534 internStringArrayList(protectedBroadcasts);
6535
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006536 parentPackage = dest.readParcelable(boot);
6537
6538 childPackages = new ArrayList<>();
6539 dest.readParcelableList(childPackages, boot);
6540 if (childPackages.size() == 0) {
6541 childPackages = null;
6542 }
6543
Svet Ganov67882122016-12-11 16:36:34 -08006544 staticSharedLibName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006545 if (staticSharedLibName != null) {
6546 staticSharedLibName = staticSharedLibName.intern();
6547 }
Dianne Hackborn3accca02013-09-20 09:32:11 -07006548 staticSharedLibVersion = dest.readLong();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006549 libraryNames = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006550 internStringArrayList(libraryNames);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006551 usesLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006552 internStringArrayList(usesLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006553 usesOptionalLibraries = dest.createStringArrayList();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006554 internStringArrayList(usesOptionalLibraries);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006555 usesLibraryFiles = dest.readStringArray();
6556
Svet Ganov67882122016-12-11 16:36:34 -08006557 final int libCount = dest.readInt();
6558 if (libCount > 0) {
6559 usesStaticLibraries = new ArrayList<>(libCount);
6560 dest.readStringList(usesStaticLibraries);
Narayan Kamath07ac1442017-02-10 15:08:07 +00006561 internStringArrayList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07006562 usesStaticLibrariesVersions = new long[libCount];
6563 dest.readLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006564 usesStaticLibrariesCertDigests = new String[libCount][];
6565 for (int i = 0; i < libCount; i++) {
6566 usesStaticLibrariesCertDigests[i] = dest.createStringArray();
6567 }
Svet Ganov67882122016-12-11 16:36:34 -08006568 }
6569
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006570 preferredActivityFilters = new ArrayList<>();
6571 dest.readParcelableList(preferredActivityFilters, boot);
6572 if (preferredActivityFilters.size() == 0) {
6573 preferredActivityFilters = null;
6574 }
6575
6576 mOriginalPackages = dest.createStringArrayList();
6577 mRealPackage = dest.readString();
6578 mAdoptPermissions = dest.createStringArrayList();
6579 mAppMetaData = dest.readBundle();
6580 mVersionCode = dest.readInt();
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08006581 mVersionCodeMajor = dest.readInt();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006582 mVersionName = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006583 if (mVersionName != null) {
6584 mVersionName = mVersionName.intern();
6585 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006586 mSharedUserId = dest.readString();
Narayan Kamath07ac1442017-02-10 15:08:07 +00006587 if (mSharedUserId != null) {
6588 mSharedUserId = mSharedUserId.intern();
6589 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006590 mSharedUserLabel = dest.readInt();
6591
Patrick Baumann47117fc2017-12-19 10:17:21 -08006592 mSigningDetails = dest.readParcelable(boot);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006593
6594 mPreferredOrder = dest.readInt();
6595
6596 // long[] packageUsageTimeMillis is not persisted because it isn't information that
6597 // is parsed from the APK.
6598
6599 // Object mExtras is not persisted because it is not information that is read from
6600 // the APK, rather, it is supplied by callers.
6601
6602
6603 configPreferences = new ArrayList<>();
6604 dest.readParcelableList(configPreferences, boot);
6605 if (configPreferences.size() == 0) {
6606 configPreferences = null;
6607 }
6608
6609 reqFeatures = new ArrayList<>();
6610 dest.readParcelableList(reqFeatures, boot);
6611 if (reqFeatures.size() == 0) {
6612 reqFeatures = null;
6613 }
6614
6615 featureGroups = new ArrayList<>();
6616 dest.readParcelableList(featureGroups, boot);
6617 if (featureGroups.size() == 0) {
6618 featureGroups = null;
6619 }
6620
6621 installLocation = dest.readInt();
6622 coreApp = (dest.readInt() == 1);
6623 mRequiredForAllUsers = (dest.readInt() == 1);
6624 mRestrictedAccountType = dest.readString();
6625 mRequiredAccountType = dest.readString();
6626 mOverlayTarget = dest.readString();
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006627 mOverlayPriority = dest.readInt();
Jaekyun Seok04342892017-03-02 15:24:19 +09006628 mIsStaticOverlay = (dest.readInt() == 1);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006629 mTrustedOverlay = (dest.readInt() == 1);
Alan Viveretteb6a25732017-11-21 14:49:24 -05006630 mCompileSdkVersion = dest.readInt();
6631 mCompileSdkVersionCodename = dest.readString();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006632 mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
6633
6634 mKeySetMapping = readKeySetMapping(dest);
6635
6636 cpuAbiOverride = dest.readString();
6637 use32bitAbi = (dest.readInt() == 1);
6638 restrictUpdateHash = dest.createByteArray();
Chad Brubaker49f24c62017-04-05 13:08:21 -07006639 visibleToInstantApps = dest.readInt() == 1;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006640 }
6641
Narayan Kamath07ac1442017-02-10 15:08:07 +00006642 private static void internStringArrayList(List<String> list) {
6643 if (list != null) {
6644 final int N = list.size();
6645 for (int i = 0; i < N; ++i) {
6646 list.set(i, list.get(i).intern());
6647 }
6648 }
6649 }
6650
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006651 /**
6652 * Sets the package owner and the the {@code applicationInfo} for every component
6653 * owner by this package.
6654 */
6655 private void fixupOwner(List<? extends Component<?>> list) {
6656 if (list != null) {
6657 for (Component<?> c : list) {
6658 c.owner = this;
6659 if (c instanceof Activity) {
6660 ((Activity) c).info.applicationInfo = this.applicationInfo;
6661 } else if (c instanceof Service) {
6662 ((Service) c).info.applicationInfo = this.applicationInfo;
6663 } else if (c instanceof Provider) {
6664 ((Provider) c).info.applicationInfo = this.applicationInfo;
6665 }
6666 }
6667 }
6668 }
6669
6670 @Override
6671 public void writeToParcel(Parcel dest, int flags) {
6672 dest.writeString(packageName);
Svet Ganov67882122016-12-11 16:36:34 -08006673 dest.writeString(manifestPackageName);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006674 dest.writeStringArray(splitNames);
6675 dest.writeString(volumeUuid);
6676 dest.writeString(codePath);
6677 dest.writeString(baseCodePath);
6678 dest.writeStringArray(splitCodePaths);
6679 dest.writeInt(baseRevisionCode);
6680 dest.writeIntArray(splitRevisionCodes);
6681 dest.writeIntArray(splitFlags);
6682 dest.writeIntArray(splitPrivateFlags);
6683 dest.writeInt(baseHardwareAccelerated ? 1 : 0);
6684 dest.writeParcelable(applicationInfo, flags);
6685
6686 dest.writeParcelableList(permissions, flags);
6687 dest.writeParcelableList(permissionGroups, flags);
6688 dest.writeParcelableList(activities, flags);
6689 dest.writeParcelableList(receivers, flags);
6690 dest.writeParcelableList(providers, flags);
6691 dest.writeParcelableList(services, flags);
6692 dest.writeParcelableList(instrumentation, flags);
6693
6694 dest.writeStringList(requestedPermissions);
6695 dest.writeStringList(protectedBroadcasts);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07006696
6697 // TODO: This doesn't work: b/64295061
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006698 dest.writeParcelable(parentPackage, flags);
6699 dest.writeParcelableList(childPackages, flags);
Makoto Onuki4501c61d2017-07-27 15:56:40 -07006700
Svet Ganov67882122016-12-11 16:36:34 -08006701 dest.writeString(staticSharedLibName);
Dianne Hackborn3accca02013-09-20 09:32:11 -07006702 dest.writeLong(staticSharedLibVersion);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006703 dest.writeStringList(libraryNames);
6704 dest.writeStringList(usesLibraries);
6705 dest.writeStringList(usesOptionalLibraries);
6706 dest.writeStringArray(usesLibraryFiles);
6707
Svet Ganov67882122016-12-11 16:36:34 -08006708 if (ArrayUtils.isEmpty(usesStaticLibraries)) {
6709 dest.writeInt(-1);
6710 } else {
6711 dest.writeInt(usesStaticLibraries.size());
6712 dest.writeStringList(usesStaticLibraries);
Dianne Hackborn3accca02013-09-20 09:32:11 -07006713 dest.writeLongArray(usesStaticLibrariesVersions);
Svetoslav Ganovcdd685c2017-08-22 14:35:04 -07006714 for (String[] usesStaticLibrariesCertDigest : usesStaticLibrariesCertDigests) {
6715 dest.writeStringArray(usesStaticLibrariesCertDigest);
6716 }
Svet Ganov67882122016-12-11 16:36:34 -08006717 }
6718
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006719 dest.writeParcelableList(preferredActivityFilters, flags);
6720
6721 dest.writeStringList(mOriginalPackages);
6722 dest.writeString(mRealPackage);
6723 dest.writeStringList(mAdoptPermissions);
6724 dest.writeBundle(mAppMetaData);
6725 dest.writeInt(mVersionCode);
Todd Kennedy5b1df2f2017-12-11 13:26:14 -08006726 dest.writeInt(mVersionCodeMajor);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006727 dest.writeString(mVersionName);
6728 dest.writeString(mSharedUserId);
6729 dest.writeInt(mSharedUserLabel);
6730
Patrick Baumann47117fc2017-12-19 10:17:21 -08006731 dest.writeParcelable(mSigningDetails, flags);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006732
6733 dest.writeInt(mPreferredOrder);
6734
6735 // long[] packageUsageTimeMillis is not persisted because it isn't information that
6736 // is parsed from the APK.
6737
6738 // Object mExtras is not persisted because it is not information that is read from
6739 // the APK, rather, it is supplied by callers.
6740
6741 dest.writeParcelableList(configPreferences, flags);
6742 dest.writeParcelableList(reqFeatures, flags);
6743 dest.writeParcelableList(featureGroups, flags);
6744
6745 dest.writeInt(installLocation);
6746 dest.writeInt(coreApp ? 1 : 0);
6747 dest.writeInt(mRequiredForAllUsers ? 1 : 0);
6748 dest.writeString(mRestrictedAccountType);
6749 dest.writeString(mRequiredAccountType);
6750 dest.writeString(mOverlayTarget);
Jaekyun Seok42d53f62017-04-10 13:48:58 +09006751 dest.writeInt(mOverlayPriority);
Jaekyun Seok04342892017-03-02 15:24:19 +09006752 dest.writeInt(mIsStaticOverlay ? 1 : 0);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006753 dest.writeInt(mTrustedOverlay ? 1 : 0);
Alan Viveretteb6a25732017-11-21 14:49:24 -05006754 dest.writeInt(mCompileSdkVersion);
6755 dest.writeString(mCompileSdkVersionCodename);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006756 dest.writeArraySet(mUpgradeKeySets);
6757 writeKeySetMapping(dest, mKeySetMapping);
6758 dest.writeString(cpuAbiOverride);
6759 dest.writeInt(use32bitAbi ? 1 : 0);
6760 dest.writeByteArray(restrictUpdateHash);
Chad Brubaker49f24c62017-04-05 13:08:21 -07006761 dest.writeInt(visibleToInstantApps ? 1 : 0);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006762 }
6763
6764
6765 /**
6766 * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
6767 */
6768 private static void writeKeySetMapping(
6769 Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
6770 if (keySetMapping == null) {
6771 dest.writeInt(-1);
6772 return;
6773 }
6774
6775 final int N = keySetMapping.size();
6776 dest.writeInt(N);
6777
6778 for (int i = 0; i < N; i++) {
6779 dest.writeString(keySetMapping.keyAt(i));
6780 ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
6781 if (keys == null) {
6782 dest.writeInt(-1);
6783 continue;
6784 }
6785
6786 final int M = keys.size();
6787 dest.writeInt(M);
6788 for (int j = 0; j < M; j++) {
6789 dest.writeSerializable(keys.valueAt(j));
6790 }
6791 }
6792 }
6793
6794 /**
6795 * Reads a keyset mapping from the given parcel at the given data position. May return
6796 * {@code null} if the serialized mapping was {@code null}.
6797 */
6798 private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
6799 final int N = in.readInt();
6800 if (N == -1) {
6801 return null;
6802 }
6803
6804 ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
6805 for (int i = 0; i < N; ++i) {
6806 String key = in.readString();
6807 final int M = in.readInt();
6808 if (M == -1) {
6809 keySetMapping.put(key, null);
6810 continue;
6811 }
6812
6813 ArraySet<PublicKey> keys = new ArraySet<>(M);
6814 for (int j = 0; j < M; ++j) {
6815 PublicKey pk = (PublicKey) in.readSerializable();
6816 keys.add(pk);
6817 }
6818
6819 keySetMapping.put(key, keys);
6820 }
6821
6822 return keySetMapping;
6823 }
6824
6825 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
6826 public Package createFromParcel(Parcel in) {
6827 return new Package(in);
6828 }
6829
6830 public Package[] newArray(int size) {
6831 return new Package[size];
6832 }
6833 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006834 }
6835
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006836 public static abstract class Component<II extends IntentInfo> {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006837 public final ArrayList<II> intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006838 public final String className;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006840 public Bundle metaData;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006841 public Package owner;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006842
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006843 ComponentName componentName;
6844 String componentShortName;
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006845
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006846 public Component(Package _owner) {
6847 owner = _owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006848 intents = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006849 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006850 }
6851
6852 public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
6853 owner = args.owner;
6854 intents = new ArrayList<II>(0);
Todd Kennedybb8a42d2016-06-02 14:13:56 -07006855 if (parsePackageItemInfo(args.owner, outInfo, args.outError, args.tag, args.sa,
6856 true /*nameRequired*/, args.nameRes, args.labelRes, args.iconRes,
6857 args.roundIconRes, args.logoRes, args.bannerRes)) {
6858 className = outInfo.name;
6859 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006860 className = null;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006861 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006862 }
6863
6864 public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
6865 this(args, (PackageItemInfo)outInfo);
6866 if (args.outError[0] != null) {
6867 return;
6868 }
6869
6870 if (args.processRes != 0) {
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07006871 CharSequence pname;
6872 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
Dianne Hackborn1d0b1772013-09-06 14:02:54 -07006873 pname = args.sa.getNonConfigurationString(args.processRes,
6874 Configuration.NATIVE_CONFIG_VERSION);
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07006875 } else {
6876 // Some older apps have been seen to use a resource reference
6877 // here that on older builds was ignored (with a warning). We
6878 // need to continue to do this for them so they don't break.
6879 pname = args.sa.getNonResourceString(args.processRes);
6880 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006881 outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
Dianne Hackbornd1cff1b2010-04-02 16:51:26 -07006882 owner.applicationInfo.processName, pname,
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006883 args.flags, args.sepProcesses, args.outError);
6884 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006885
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08006886 if (args.descriptionRes != 0) {
6887 outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
6888 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006889
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006890 outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006891 }
6892
6893 public Component(Component<II> clone) {
6894 owner = clone.owner;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006895 intents = clone.intents;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006896 className = clone.className;
6897 componentName = clone.componentName;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006898 componentShortName = clone.componentShortName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006899 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07006900
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006901 public ComponentName getComponentName() {
6902 if (componentName != null) {
6903 return componentName;
6904 }
6905 if (className != null) {
6906 componentName = new ComponentName(owner.applicationInfo.packageName,
6907 className);
6908 }
6909 return componentName;
6910 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07006911
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00006912 protected Component(Parcel in) {
6913 className = in.readString();
6914 metaData = in.readBundle();
6915 intents = createIntentsList(in);
6916
6917 owner = null;
6918 }
6919
6920 protected void writeToParcel(Parcel dest, int flags) {
6921 dest.writeString(className);
6922 dest.writeBundle(metaData);
6923
6924 writeIntentsList(intents, dest, flags);
6925 }
6926
6927 /**
6928 * <p>
6929 * Implementation note: The serialized form for the intent list also contains the name
6930 * of the concrete class that's stored in the list, and assumes that every element of the
6931 * list is of the same type. This is very similar to the original parcelable mechanism.
6932 * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable
6933 * and is public API. It also declares Parcelable related methods as final which means
6934 * we can't extend them. The approach of using composition instead of inheritance leads to
6935 * a large set of cascading changes in the PackageManagerService, which seem undesirable.
6936 *
6937 * <p>
6938 * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up
6939 * to make sure their owner fields are consistent. See {@code fixupOwner}.
6940 */
6941 private static void writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out,
6942 int flags) {
6943 if (list == null) {
6944 out.writeInt(-1);
6945 return;
6946 }
6947
6948 final int N = list.size();
6949 out.writeInt(N);
6950
6951 // Don't bother writing the component name if the list is empty.
6952 if (N > 0) {
6953 IntentInfo info = list.get(0);
6954 out.writeString(info.getClass().getName());
6955
6956 for (int i = 0; i < N;i++) {
6957 list.get(i).writeIntentInfoToParcel(out, flags);
6958 }
6959 }
6960 }
6961
6962 private static <T extends IntentInfo> ArrayList<T> createIntentsList(Parcel in) {
6963 int N = in.readInt();
6964 if (N == -1) {
6965 return null;
6966 }
6967
6968 if (N == 0) {
6969 return new ArrayList<>(0);
6970 }
6971
6972 String componentName = in.readString();
6973 final ArrayList<T> intentsList;
6974 try {
6975 final Class<T> cls = (Class<T>) Class.forName(componentName);
6976 final Constructor<T> cons = cls.getConstructor(Parcel.class);
6977
6978 intentsList = new ArrayList<>(N);
6979 for (int i = 0; i < N; ++i) {
6980 intentsList.add(cons.newInstance(in));
6981 }
6982 } catch (ReflectiveOperationException ree) {
6983 throw new AssertionError("Unable to construct intent list for: " + componentName);
6984 }
6985
6986 return intentsList;
6987 }
6988
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07006989 public void appendComponentShortName(StringBuilder sb) {
6990 ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006991 }
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07006992
6993 public void printComponentShortName(PrintWriter pw) {
6994 ComponentName.printShortString(pw, owner.applicationInfo.packageName, className);
6995 }
6996
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006997 public void setPackageName(String packageName) {
6998 componentName = null;
6999 componentShortName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007000 }
7001 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007002
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007003 public final static class Permission extends Component<IntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007004 public final PermissionInfo info;
7005 public boolean tree;
7006 public PermissionGroup group;
7007
7008 public Permission(Package _owner) {
7009 super(_owner);
7010 info = new PermissionInfo();
7011 }
7012
7013 public Permission(Package _owner, PermissionInfo _info) {
7014 super(_owner);
7015 info = _info;
7016 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007017
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007018 public void setPackageName(String packageName) {
7019 super.setPackageName(packageName);
7020 info.packageName = packageName;
7021 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007022
7023 public String toString() {
7024 return "Permission{"
7025 + Integer.toHexString(System.identityHashCode(this))
7026 + " " + info.name + "}";
7027 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007028
7029 @Override
7030 public int describeContents() {
7031 return 0;
7032 }
7033
7034 @Override
7035 public void writeToParcel(Parcel dest, int flags) {
7036 super.writeToParcel(dest, flags);
7037 dest.writeParcelable(info, flags);
7038 dest.writeInt(tree ? 1 : 0);
7039 dest.writeParcelable(group, flags);
7040 }
7041
Todd Kennedyc8423932017-10-05 08:58:36 -07007042 /** @hide */
7043 public boolean isAppOp() {
7044 return info.isAppOp();
7045 }
7046
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007047 private Permission(Parcel in) {
7048 super(in);
7049 final ClassLoader boot = Object.class.getClassLoader();
7050 info = in.readParcelable(boot);
Narayan Kamath07ac1442017-02-10 15:08:07 +00007051 if (info.group != null) {
7052 info.group = info.group.intern();
7053 }
7054
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007055 tree = (in.readInt() == 1);
7056 group = in.readParcelable(boot);
7057 }
7058
7059 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Permission>() {
7060 public Permission createFromParcel(Parcel in) {
7061 return new Permission(in);
7062 }
7063
7064 public Permission[] newArray(int size) {
7065 return new Permission[size];
7066 }
7067 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007068 }
7069
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007070 public final static class PermissionGroup extends Component<IntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007071 public final PermissionGroupInfo info;
7072
7073 public PermissionGroup(Package _owner) {
7074 super(_owner);
7075 info = new PermissionGroupInfo();
7076 }
7077
7078 public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
7079 super(_owner);
7080 info = _info;
7081 }
7082
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007083 public void setPackageName(String packageName) {
7084 super.setPackageName(packageName);
7085 info.packageName = packageName;
7086 }
7087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007088 public String toString() {
7089 return "PermissionGroup{"
7090 + Integer.toHexString(System.identityHashCode(this))
7091 + " " + info.name + "}";
7092 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007093
7094 @Override
7095 public int describeContents() {
7096 return 0;
7097 }
7098
7099 @Override
7100 public void writeToParcel(Parcel dest, int flags) {
7101 super.writeToParcel(dest, flags);
7102 dest.writeParcelable(info, flags);
7103 }
7104
7105 private PermissionGroup(Parcel in) {
7106 super(in);
7107 info = in.readParcelable(Object.class.getClassLoader());
7108 }
7109
7110 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<PermissionGroup>() {
7111 public PermissionGroup createFromParcel(Parcel in) {
7112 return new PermissionGroup(in);
7113 }
7114
7115 public PermissionGroup[] newArray(int size) {
7116 return new PermissionGroup[size];
7117 }
7118 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007119 }
7120
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007121 private static boolean copyNeeded(int flags, Package p,
7122 PackageUserState state, Bundle metaData, int userId) {
Xiaohui Chen98404fd2015-08-17 16:09:02 -07007123 if (userId != UserHandle.USER_SYSTEM) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007124 // We always need to copy for other users, since we need
7125 // to fix up the uid.
7126 return true;
7127 }
7128 if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
7129 boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07007130 if (p.applicationInfo.enabled != enabled) {
7131 return true;
7132 }
7133 }
Rubin Xubf67c9c2016-04-20 17:09:38 +01007134 boolean suspended = (p.applicationInfo.flags & FLAG_SUSPENDED) != 0;
7135 if (state.suspended != suspended) {
7136 return true;
7137 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007138 if (!state.installed || state.hidden) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007139 return true;
7140 }
7141 if (state.stopped) {
7142 return true;
7143 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007144 if (state.instantApp != p.applicationInfo.isInstantApp()) {
7145 return true;
7146 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007147 if ((flags & PackageManager.GET_META_DATA) != 0
7148 && (metaData != null || p.mAppMetaData != null)) {
7149 return true;
7150 }
7151 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
7152 && p.usesLibraryFiles != null) {
7153 return true;
7154 }
Svet Ganov67882122016-12-11 16:36:34 -08007155 if (p.staticSharedLibName != null) {
7156 return true;
7157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007158 return false;
7159 }
7160
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007161 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
7162 PackageUserState state) {
7163 return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId());
Amith Yamasani742a6712011-05-04 14:49:28 -07007164 }
7165
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007166 private static void updateApplicationInfo(ApplicationInfo ai, int flags,
7167 PackageUserState state) {
7168 // CompatibilityMode is global state.
7169 if (!sCompatibilityModeEnabled) {
7170 ai.disableCompatibilityMode();
7171 }
7172 if (state.installed) {
7173 ai.flags |= ApplicationInfo.FLAG_INSTALLED;
7174 } else {
7175 ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
7176 }
Andrei Stingaceanu1e283912015-11-26 15:26:28 +00007177 if (state.suspended) {
7178 ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
7179 } else {
7180 ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
7181 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007182 if (state.instantApp) {
7183 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT;
7184 } else {
7185 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT;
7186 }
Todd Kennedy5eb5a7d2017-08-01 07:42:47 -07007187 if (state.virtualPreload) {
7188 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7189 } else {
7190 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
7191 }
Amith Yamasanie5bcff62014-07-19 15:44:09 -07007192 if (state.hidden) {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007193 ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007194 } else {
Alex Klyubinb9f8a522015-02-03 11:12:59 -08007195 ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
Amith Yamasani655d0e22013-06-12 14:19:10 -07007196 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007197 if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
7198 ai.enabled = true;
7199 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
7200 ai.enabled = (flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
7201 } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
7202 || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
7203 ai.enabled = false;
7204 }
7205 ai.enabledSetting = state.enabled;
Jeff Sharkey9bc89af2017-01-11 11:25:50 -07007206 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7207 ai.category = state.categoryHint;
7208 }
Jeff Sharkey0078e1b2017-01-11 16:05:27 -07007209 if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
7210 ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
7211 }
Todd Kennedybe0b8892017-02-15 14:13:52 -08007212 ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
Todd Kennedyb2749472017-06-13 08:24:32 -07007213 ai.resourceDirs = state.overlayPaths;
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007214 }
7215
Amith Yamasani13593602012-03-22 16:16:17 -07007216 public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007217 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007218 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007219 if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007220 return null;
7221 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007222 if (!copyNeeded(flags, p, state, null, userId)
7223 && ((flags&PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
7224 || state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
7225 // In this case it is safe to directly modify the internal ApplicationInfo state:
7226 // - CompatibilityMode is global state, so will be the same for every call.
7227 // - We only come in to here if the app should reported as installed; this is the
7228 // default state, and we will do a copy otherwise.
7229 // - The enable state will always be reported the same for the application across
7230 // calls; the only exception is for the UNTIL_USED mode, and in that case we will
7231 // be doing a copy.
7232 updateApplicationInfo(p.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007233 return p.applicationInfo;
7234 }
7235
7236 // Make shallow copy so we can store the metadata/libraries safely
7237 ApplicationInfo ai = new ApplicationInfo(p.applicationInfo);
Jeff Sharkey15447792015-11-05 16:18:51 -08007238 ai.initForUser(userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007239 if ((flags & PackageManager.GET_META_DATA) != 0) {
7240 ai.metaData = p.mAppMetaData;
7241 }
7242 if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
7243 ai.sharedLibraryFiles = p.usesLibraryFiles;
7244 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007245 if (state.stopped) {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007246 ai.flags |= ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007247 } else {
Amith Yamasania4a54e22012-04-16 15:44:19 -07007248 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007249 }
Dianne Hackbornfd7aded2013-01-22 17:10:23 -08007250 updateApplicationInfo(ai, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007251 return ai;
7252 }
7253
Dianne Hackbornace27912014-09-18 18:38:30 -07007254 public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags,
7255 PackageUserState state, int userId) {
7256 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007257 if (!checkUseInstalledOrHidden(flags, state, ai)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007258 return null;
7259 }
7260 // This is only used to return the ResolverActivity; we will just always
7261 // make a copy.
7262 ai = new ApplicationInfo(ai);
Jeff Sharkey15447792015-11-05 16:18:51 -08007263 ai.initForUser(userId);
Dianne Hackbornace27912014-09-18 18:38:30 -07007264 if (state.stopped) {
7265 ai.flags |= ApplicationInfo.FLAG_STOPPED;
7266 } else {
7267 ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
7268 }
7269 updateApplicationInfo(ai, flags, state);
7270 return ai;
7271 }
7272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007273 public static final PermissionInfo generatePermissionInfo(
7274 Permission p, int flags) {
7275 if (p == null) return null;
7276 if ((flags&PackageManager.GET_META_DATA) == 0) {
7277 return p.info;
7278 }
7279 PermissionInfo pi = new PermissionInfo(p.info);
7280 pi.metaData = p.metaData;
7281 return pi;
7282 }
7283
7284 public static final PermissionGroupInfo generatePermissionGroupInfo(
7285 PermissionGroup pg, int flags) {
7286 if (pg == null) return null;
7287 if ((flags&PackageManager.GET_META_DATA) == 0) {
7288 return pg.info;
7289 }
7290 PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info);
7291 pgi.metaData = pg.metaData;
7292 return pgi;
7293 }
7294
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007295 public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007296 public final ActivityInfo info;
Bryce Lee22571db2017-07-07 15:54:18 -07007297 private boolean mHasMaxAspectRatio;
7298
7299 private boolean hasMaxAspectRatio() {
7300 return mHasMaxAspectRatio;
7301 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007302
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007303 public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
7304 super(args, _info);
7305 info = _info;
7306 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007307 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007308
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007309 public void setPackageName(String packageName) {
7310 super.setPackageName(packageName);
7311 info.packageName = packageName;
7312 }
7313
Bryce Lee22571db2017-07-07 15:54:18 -07007314
7315 private void setMaxAspectRatio(float maxAspectRatio) {
7316 if (info.resizeMode == RESIZE_MODE_RESIZEABLE
7317 || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
7318 // Resizeable activities can be put in any aspect ratio.
7319 return;
7320 }
7321
7322 if (maxAspectRatio < 1.0f && maxAspectRatio != 0) {
7323 // Ignore any value lesser than 1.0.
7324 return;
7325 }
7326
7327 info.maxAspectRatio = maxAspectRatio;
7328 mHasMaxAspectRatio = true;
7329 }
7330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007331 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007332 StringBuilder sb = new StringBuilder(128);
7333 sb.append("Activity{");
7334 sb.append(Integer.toHexString(System.identityHashCode(this)));
7335 sb.append(' ');
7336 appendComponentShortName(sb);
7337 sb.append('}');
7338 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007339 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007340
7341 @Override
7342 public int describeContents() {
7343 return 0;
7344 }
7345
7346 @Override
7347 public void writeToParcel(Parcel dest, int flags) {
7348 super.writeToParcel(dest, flags);
7349 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
Bryce Lee22571db2017-07-07 15:54:18 -07007350 dest.writeBoolean(mHasMaxAspectRatio);
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007351 }
7352
7353 private Activity(Parcel in) {
7354 super(in);
7355 info = in.readParcelable(Object.class.getClassLoader());
Bryce Lee22571db2017-07-07 15:54:18 -07007356 mHasMaxAspectRatio = in.readBoolean();
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007357
7358 for (ActivityIntentInfo aii : intents) {
7359 aii.activity = this;
7360 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007361
7362 if (info.permission != null) {
7363 info.permission = info.permission.intern();
7364 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007365 }
7366
7367 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Activity>() {
7368 public Activity createFromParcel(Parcel in) {
7369 return new Activity(in);
7370 }
7371
7372 public Activity[] newArray(int size) {
7373 return new Activity[size];
7374 }
7375 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007376 }
7377
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007378 public static final ActivityInfo generateActivityInfo(Activity a, int flags,
7379 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007380 if (a == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007381 if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007382 return null;
7383 }
7384 if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007385 updateApplicationInfo(a.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007386 return a.info;
7387 }
7388 // Make shallow copies so we can store the metadata safely
7389 ActivityInfo ai = new ActivityInfo(a.info);
7390 ai.metaData = a.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007391 ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007392 return ai;
7393 }
7394
Dianne Hackbornace27912014-09-18 18:38:30 -07007395 public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags,
7396 PackageUserState state, int userId) {
7397 if (ai == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007398 if (!checkUseInstalledOrHidden(flags, state, ai.applicationInfo)) {
Dianne Hackbornace27912014-09-18 18:38:30 -07007399 return null;
7400 }
7401 // This is only used to return the ResolverActivity; we will just always
7402 // make a copy.
7403 ai = new ActivityInfo(ai);
7404 ai.applicationInfo = generateApplicationInfo(ai.applicationInfo, flags, state, userId);
7405 return ai;
7406 }
7407
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007408 public final static class Service extends Component<ServiceIntentInfo> implements Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007409 public final ServiceInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007410
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007411 public Service(final ParseComponentArgs args, final ServiceInfo _info) {
7412 super(args, _info);
7413 info = _info;
7414 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007415 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007416
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007417 public void setPackageName(String packageName) {
7418 super.setPackageName(packageName);
7419 info.packageName = packageName;
7420 }
7421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007422 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007423 StringBuilder sb = new StringBuilder(128);
7424 sb.append("Service{");
7425 sb.append(Integer.toHexString(System.identityHashCode(this)));
7426 sb.append(' ');
7427 appendComponentShortName(sb);
7428 sb.append('}');
7429 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007430 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007431
7432 @Override
7433 public int describeContents() {
7434 return 0;
7435 }
7436
7437 @Override
7438 public void writeToParcel(Parcel dest, int flags) {
7439 super.writeToParcel(dest, flags);
7440 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
7441 }
7442
7443 private Service(Parcel in) {
7444 super(in);
7445 info = in.readParcelable(Object.class.getClassLoader());
7446
7447 for (ServiceIntentInfo aii : intents) {
7448 aii.service = this;
7449 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007450
7451 if (info.permission != null) {
7452 info.permission = info.permission.intern();
7453 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007454 }
7455
7456 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Service>() {
7457 public Service createFromParcel(Parcel in) {
7458 return new Service(in);
7459 }
7460
7461 public Service[] newArray(int size) {
7462 return new Service[size];
7463 }
7464 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007465 }
7466
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007467 public static final ServiceInfo generateServiceInfo(Service s, int flags,
7468 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007469 if (s == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007470 if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007471 return null;
7472 }
7473 if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007474 updateApplicationInfo(s.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007475 return s.info;
7476 }
7477 // Make shallow copies so we can store the metadata safely
7478 ServiceInfo si = new ServiceInfo(s.info);
7479 si.metaData = s.metaData;
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007480 si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007481 return si;
7482 }
7483
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007484 public final static class Provider extends Component<ProviderIntentInfo> implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007485 public final ProviderInfo info;
7486 public boolean syncable;
7487
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007488 public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
7489 super(args, _info);
7490 info = _info;
7491 info.applicationInfo = args.owner.applicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007492 syncable = false;
7493 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007495 public Provider(Provider existingProvider) {
7496 super(existingProvider);
7497 this.info = existingProvider.info;
7498 this.syncable = existingProvider.syncable;
7499 }
7500
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007501 public void setPackageName(String packageName) {
7502 super.setPackageName(packageName);
7503 info.packageName = packageName;
7504 }
7505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007506 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007507 StringBuilder sb = new StringBuilder(128);
7508 sb.append("Provider{");
7509 sb.append(Integer.toHexString(System.identityHashCode(this)));
7510 sb.append(' ');
7511 appendComponentShortName(sb);
7512 sb.append('}');
7513 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007514 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007515
7516 @Override
7517 public int describeContents() {
7518 return 0;
7519 }
7520
7521 @Override
7522 public void writeToParcel(Parcel dest, int flags) {
7523 super.writeToParcel(dest, flags);
7524 dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
7525 dest.writeInt((syncable) ? 1 : 0);
7526 }
7527
7528 private Provider(Parcel in) {
7529 super(in);
7530 info = in.readParcelable(Object.class.getClassLoader());
7531 syncable = (in.readInt() == 1);
7532
7533 for (ProviderIntentInfo aii : intents) {
7534 aii.provider = this;
7535 }
Narayan Kamath07ac1442017-02-10 15:08:07 +00007536
7537 if (info.readPermission != null) {
7538 info.readPermission = info.readPermission.intern();
7539 }
7540
7541 if (info.writePermission != null) {
7542 info.writePermission = info.writePermission.intern();
7543 }
7544
7545 if (info.authority != null) {
7546 info.authority = info.authority.intern();
7547 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007548 }
7549
7550 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Provider>() {
7551 public Provider createFromParcel(Parcel in) {
7552 return new Provider(in);
7553 }
7554
7555 public Provider[] newArray(int size) {
7556 return new Provider[size];
7557 }
7558 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007559 }
7560
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007561 public static final ProviderInfo generateProviderInfo(Provider p, int flags,
7562 PackageUserState state, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007563 if (p == null) return null;
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07007564 if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007565 return null;
7566 }
7567 if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007568 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007569 || p.info.uriPermissionPatterns == null)) {
Todd Kennedyb2749472017-06-13 08:24:32 -07007570 updateApplicationInfo(p.info.applicationInfo, flags, state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007571 return p.info;
7572 }
7573 // Make shallow copies so we can store the metadata safely
7574 ProviderInfo pi = new ProviderInfo(p.info);
7575 pi.metaData = p.metaData;
7576 if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
7577 pi.uriPermissionPatterns = null;
7578 }
Dianne Hackborn7767eac2012-08-23 18:25:40 -07007579 pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007580 return pi;
7581 }
7582
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007583 public final static class Instrumentation extends Component<IntentInfo> implements
7584 Parcelable {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007585 public final InstrumentationInfo info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007586
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007587 public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
7588 super(args, _info);
7589 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007590 }
Filip Gruszczynskid2f1d942015-10-14 15:10:12 -07007591
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007592 public void setPackageName(String packageName) {
7593 super.setPackageName(packageName);
7594 info.packageName = packageName;
7595 }
7596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007597 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007598 StringBuilder sb = new StringBuilder(128);
7599 sb.append("Instrumentation{");
7600 sb.append(Integer.toHexString(System.identityHashCode(this)));
7601 sb.append(' ');
7602 appendComponentShortName(sb);
7603 sb.append('}');
7604 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007605 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007606
7607 @Override
7608 public int describeContents() {
7609 return 0;
7610 }
7611
7612 @Override
7613 public void writeToParcel(Parcel dest, int flags) {
7614 super.writeToParcel(dest, flags);
7615 dest.writeParcelable(info, flags);
7616 }
7617
7618 private Instrumentation(Parcel in) {
7619 super(in);
7620 info = in.readParcelable(Object.class.getClassLoader());
Narayan Kamath07ac1442017-02-10 15:08:07 +00007621
7622 if (info.targetPackage != null) {
7623 info.targetPackage = info.targetPackage.intern();
7624 }
7625
Dianne Hackborn1be53542017-04-28 13:36:00 -07007626 if (info.targetProcesses != null) {
7627 info.targetProcesses = info.targetProcesses.intern();
Narayan Kamath07ac1442017-02-10 15:08:07 +00007628 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007629 }
7630
7631 public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Instrumentation>() {
7632 public Instrumentation createFromParcel(Parcel in) {
7633 return new Instrumentation(in);
7634 }
7635
7636 public Instrumentation[] newArray(int size) {
7637 return new Instrumentation[size];
7638 }
7639 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007640 }
7641
7642 public static final InstrumentationInfo generateInstrumentationInfo(
7643 Instrumentation i, int flags) {
7644 if (i == null) return null;
7645 if ((flags&PackageManager.GET_META_DATA) == 0) {
7646 return i.info;
7647 }
7648 InstrumentationInfo ii = new InstrumentationInfo(i.info);
7649 ii.metaData = i.metaData;
7650 return ii;
7651 }
7652
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007653 public static abstract class IntentInfo extends IntentFilter {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007654 public boolean hasDefault;
7655 public int labelRes;
7656 public CharSequence nonLocalizedLabel;
7657 public int icon;
Adam Powell81cd2e92010-04-21 16:35:18 -07007658 public int logo;
Jose Limaf78e3122014-03-06 12:13:15 -08007659 public int banner;
Dianne Hackbornb09491f2013-07-22 15:30:11 -07007660 public int preferred;
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007661
7662 protected IntentInfo() {
7663 }
7664
7665 protected IntentInfo(Parcel dest) {
7666 super(dest);
7667 hasDefault = (dest.readInt() == 1);
7668 labelRes = dest.readInt();
7669 nonLocalizedLabel = dest.readCharSequence();
7670 icon = dest.readInt();
7671 logo = dest.readInt();
7672 banner = dest.readInt();
7673 preferred = dest.readInt();
7674 }
7675
7676
7677 public void writeIntentInfoToParcel(Parcel dest, int flags) {
7678 super.writeToParcel(dest, flags);
7679 dest.writeInt(hasDefault ? 1 : 0);
7680 dest.writeInt(labelRes);
7681 dest.writeCharSequence(nonLocalizedLabel);
7682 dest.writeInt(icon);
7683 dest.writeInt(logo);
7684 dest.writeInt(banner);
7685 dest.writeInt(preferred);
7686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007687 }
7688
7689 public final static class ActivityIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007690 public Activity activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007691
7692 public ActivityIntentInfo(Activity _activity) {
7693 activity = _activity;
7694 }
7695
7696 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007697 StringBuilder sb = new StringBuilder(128);
7698 sb.append("ActivityIntentInfo{");
7699 sb.append(Integer.toHexString(System.identityHashCode(this)));
7700 sb.append(' ');
7701 activity.appendComponentShortName(sb);
7702 sb.append('}');
7703 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007704 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007705
7706 public ActivityIntentInfo(Parcel in) {
7707 super(in);
7708 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007709 }
7710
7711 public final static class ServiceIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007712 public Service service;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007713
7714 public ServiceIntentInfo(Service _service) {
7715 service = _service;
7716 }
7717
7718 public String toString() {
Dianne Hackborn6d8dfbd2013-09-23 17:38:51 -07007719 StringBuilder sb = new StringBuilder(128);
7720 sb.append("ServiceIntentInfo{");
7721 sb.append(Integer.toHexString(System.identityHashCode(this)));
7722 sb.append(' ');
7723 service.appendComponentShortName(sb);
7724 sb.append('}');
7725 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007726 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007727
7728 public ServiceIntentInfo(Parcel in) {
7729 super(in);
7730 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007731 }
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007732
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007733 public static final class ProviderIntentInfo extends IntentInfo {
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007734 public Provider provider;
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007735
7736 public ProviderIntentInfo(Provider provider) {
7737 this.provider = provider;
7738 }
7739
7740 public String toString() {
7741 StringBuilder sb = new StringBuilder(128);
7742 sb.append("ProviderIntentInfo{");
7743 sb.append(Integer.toHexString(System.identityHashCode(this)));
7744 sb.append(' ');
7745 provider.appendComponentShortName(sb);
7746 sb.append('}');
7747 return sb.toString();
7748 }
Narayan Kamathfb2afbf2016-11-24 13:22:40 +00007749
7750 public ProviderIntentInfo(Parcel in) {
7751 super(in);
7752 }
Jeff Sharkey85f5f812013-10-07 10:16:12 -07007753 }
7754
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007755 /**
7756 * @hide
7757 */
7758 public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
7759 sCompatibilityModeEnabled = compatibilityModeEnabled;
7760 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07007761
7762 public static class PackageParserException extends Exception {
7763 public final int error;
7764
7765 public PackageParserException(int error, String detailMessage) {
7766 super(detailMessage);
7767 this.error = error;
7768 }
Jeff Sharkey275e0852014-06-17 18:18:49 -07007769
7770 public PackageParserException(int error, String detailMessage, Throwable throwable) {
7771 super(detailMessage, throwable);
7772 this.error = error;
7773 }
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07007774 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007775}